Skip to content

Track Distribution Documentation

Overview

The Track Distribution model (track.distrib) defines templates for distributing financial amounts across multiple tracking categories. It enables percentage-based allocation of costs, revenues, or other amounts to different cost centers, projects, or departments.


Model Information

Model Name: track.distrib Display Name: Tracking Distribution Key Fields: None (no unique constraint defined)

Features

  • ❌ Audit logging enabled (_audit_log)
  • ❌ Multi-company support (company_id)
  • ❌ Full-text content search (_content_search)
  • ✅ Computed display name with percentages
  • ✅ Searchable by line track codes/names
  • ✅ Flexible ratio-based allocation

Key Fields Reference

All Fields

Field Type Required Description
name Char Computed display name
lines One2Many Distribution line items

Default Ordering

Records are ordered by ID descending (newest first):

_order = "id desc"

API Methods

1. Get Name

Method: get_name(ids, context={}, **kw)

Generates a descriptive name showing all allocation percentages.

Format:

PD-XXXX:
- Category1: XX%
- Category2: XX%

Example:

distrib = get_model("track.distrib").browse([distrib_id])[0]
print(distrib.name)
# Output:
# PD-0001:
# - Marketing: 30%
# - Sales: 70%


Method: name_search(name, condition=None, limit=None, context={})

Searches distributions by track category code or name.

Behavior: - Searches lines.track_id.code (ilike) - Searches lines.track_id.name (ilike)

Example:

# Find distributions containing "MKT" category
results = get_model("track.distrib").name_search("MKT")
# Returns distributions that include Marketing category


Model Relationship Description
track.distrib.line One2Many (lines) Distribution lines
account.track.categ via lines Target tracking categories

Common Use Cases

Use Case 1: Create Overhead Distribution

# Create distribution for overhead costs
distrib_id = get_model("track.distrib").create({})

# Add distribution lines
get_model("track.distrib.line").create({
    "distrib_id": distrib_id,
    "track_id": sales_track_id,
    "ratio": 60,
})

get_model("track.distrib.line").create({
    "distrib_id": distrib_id,
    "track_id": admin_track_id,
    "ratio": 25,
})

get_model("track.distrib.line").create({
    "distrib_id": distrib_id,
    "track_id": support_track_id,
    "ratio": 15,
})

# Percentages: Sales 60%, Admin 25%, Support 15%

Use Case 2: Apply Distribution to Amount

# Get distribution template
distrib = get_model("track.distrib").browse([distrib_id])[0]

# Amount to distribute
total_amount = 10000.00

# Calculate allocation
allocations = []
for line in distrib.lines:
    allocated = total_amount * (line.percent / 100)
    allocations.append({
        "track_id": line.track_id.id,
        "track_name": line.track_id.name,
        "percent": line.percent,
        "amount": allocated,
    })

# Print allocation
print(f"Distributing {total_amount:,.2f}")
for alloc in allocations:
    print(f"  {alloc['track_name']}: {alloc['percent']:.0f}% = {alloc['amount']:,.2f}")

Use Case 3: Create Project Cost Sharing

# Distribution for shared project costs
distrib_id = get_model("track.distrib").create({})

# Equal split between 3 projects
projects = [project_a_id, project_b_id, project_c_id]
for project_id in projects:
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": project_id,
        "ratio": 1,  # Equal ratio
    })

# Each project gets 33.33%

Use Case 4: Department Budget Allocation

# Annual budget distribution template
distrib = get_model("track.distrib").browse([budget_distrib_id])[0]

annual_budget = 1000000.00

print("Budget Allocation")
print("-" * 40)
for line in distrib.lines:
    dept_budget = annual_budget * (line.percent / 100)
    print(f"{line.track_id.name}: {line.percent:.1f}% = ${dept_budget:,.0f}")

Use Case 5: Find Distribution by Category

# Find all distributions that include a specific category
track_code = "MKT"
distribs = get_model("track.distrib").search_browse([
    ["lines.track_id.code", "=", track_code]
])

print(f"Distributions including {track_code}:")
for distrib in distribs:
    print(f"  {distrib.name}")

Distribution Structure

Track Distribution (track.distrib)
├── Distribution ID: PD-0001
└── Lines (track.distrib.line)
    ├── Line 1: Marketing (ratio: 3, percent: 30%)
    ├── Line 2: Sales (ratio: 5, percent: 50%)
    └── Line 3: Support (ratio: 2, percent: 20%)

Total ratio: 3 + 5 + 2 = 10
Percentages: 30% + 50% + 20% = 100%

Best Practices

1. Use Meaningful Ratios

# Good: Ratios that reflect actual allocation
lines = [
    {"track_id": sales_id, "ratio": 60},    # 60%
    {"track_id": admin_id, "ratio": 30},    # 30%
    {"track_id": it_id, "ratio": 10},       # 10%
]

# Also good: Simple ratios for equal split
lines = [
    {"track_id": proj_a_id, "ratio": 1},    # 33.33%
    {"track_id": proj_b_id, "ratio": 1},    # 33.33%
    {"track_id": proj_c_id, "ratio": 1},    # 33.33%
]

2. Ensure Complete Allocation

# Good: All ratios add up meaningfully
# Percentages automatically calculated from ratios

# Verify total is 100%
distrib = get_model("track.distrib").browse([distrib_id])[0]
total_percent = sum(line.percent for line in distrib.lines)
assert abs(total_percent - 100) < 0.01, "Distribution should total 100%"

3. Document Distribution Purpose

# Create with descriptive categories
# The name field auto-generates from lines

# Use track categories with clear names
# e.g., "Sales - North", "Sales - South"
# Distribution name becomes:
# PD-0001:
# - Sales - North: 50%
# - Sales - South: 50%

Troubleshooting

"Distribution shows 0%"

Cause: Lines have ratio = 0 or no lines Solution: Set ratio > 0 on distribution lines

"Percentages don't add to 100%"

Cause: This is expected - percentages are calculated from ratios Solution: Ratios are relative; system calculates percentages automatically

"Can't find distribution"

Cause: Search by track name/code not matching Solution: Use name_search which searches line track codes/names


Testing Examples

Unit Test: Distribution Creation

def test_track_distribution():
    # Create distribution
    distrib_id = get_model("track.distrib").create({})

    # Add lines
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_a_id,
        "ratio": 3,
    })
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_b_id,
        "ratio": 1,
    })

    # Verify
    distrib = get_model("track.distrib").browse([distrib_id])[0]
    assert len(distrib.lines) == 2

    # Check percentages (3:1 ratio = 75:25)
    percents = {l.track_id.id: l.percent for l in distrib.lines}
    assert percents[track_a_id] == 75.0
    assert percents[track_b_id] == 25.0

    # Cleanup
    get_model("track.distrib").delete([distrib_id])

Security Considerations

Permission Model

  • Distribution templates are typically shared
  • Requires track category access for line creation

Data Integrity

  • Cascade delete removes lines when distribution deleted
  • Track categories must exist before adding to distribution

Version History

Last Updated: December 2024 Model Version: track_distrib.py Framework: Netforce


Additional Resources

  • Distribution Line Documentation: track.distrib.line
  • Track Category Documentation: account.track.categ
  • Track Entry Documentation: account.track.entry

This documentation is generated for developer onboarding and reference purposes.