Skip to content

Track Distribution Line Documentation

Overview

The Track Distribution Line model (track.distrib.line) represents individual allocation entries within a tracking distribution template. Each line specifies a tracking category and its ratio for receiving a portion of distributed amounts.


Model Information

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

Features

  • ❌ Audit logging enabled (_audit_log)
  • ❌ Multi-company support (company_id)
  • ❌ Full-text content search (_content_search)
  • ✅ Cascade delete with parent distribution
  • ✅ Computed percentage from ratio
  • ✅ Automatic recalculation when ratios change

Key Fields Reference

All Fields

Field Type Required Description
distrib_id Many2One Parent distribution (cascade delete)
track_id Many2One Target tracking category
ratio Decimal Allocation ratio
percent Decimal Computed percentage

API Methods

1. Get Percent

Method: get_percent(ids, context={})

Calculates the percentage allocation for each line based on total ratios.

Formula:

percent = (line.ratio / sum_of_all_ratios) × 100

Behavior: 1. Groups lines by distribution 2. Calculates total ratio for each distribution 3. Computes percentage for requested lines 4. Returns None if total ratio is 0

Example:

# Distribution with lines:
# Line A: ratio = 3
# Line B: ratio = 2
# Total ratio = 5

# Calculated percentages:
# Line A: (3/5) × 100 = 60%
# Line B: (2/5) × 100 = 40%


Model Relationship Description
track.distrib Many2One (distrib_id) Parent distribution
account.track.categ Many2One (track_id) Target tracking category

Common Use Cases

Use Case 1: Create Distribution Lines

# Create distribution with lines
distrib_id = get_model("track.distrib").create({})

# Add department allocations
allocations = [
    (sales_track_id, 5),      # 50%
    (marketing_track_id, 3),  # 30%
    (support_track_id, 2),    # 20%
]

for track_id, ratio in allocations:
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_id,
        "ratio": ratio,
    })

Use Case 2: Update Line Ratio

# Change allocation ratio
line = get_model("track.distrib.line").browse([line_id])[0]
print(f"Current: {line.ratio} ({line.percent}%)")

# Update ratio
get_model("track.distrib.line").write([line_id], {
    "ratio": 4,
})

# Percentages recalculate automatically
line = get_model("track.distrib.line").browse([line_id])[0]
print(f"Updated: {line.ratio} ({line.percent}%)")

Use Case 3: Get Distribution Breakdown

# Get all lines for a distribution
lines = get_model("track.distrib.line").search_browse([
    ["distrib_id", "=", distrib_id]
])

print("Distribution Breakdown:")
print("-" * 40)
for line in lines:
    print(f"  {line.track_id.name}: {line.ratio} ({line.percent:.1f}%)")

Use Case 4: Calculate Allocated Amounts

# Apply distribution to an amount
total_amount = 15000.00

lines = get_model("track.distrib.line").search_browse([
    ["distrib_id", "=", distrib_id]
])

print(f"Allocating ${total_amount:,.2f}")
print("-" * 40)

allocated_total = 0
for line in lines:
    allocated = total_amount * (line.percent / 100)
    allocated_total += allocated
    print(f"  {line.track_id.code}: {line.percent:.1f}% = ${allocated:,.2f}")

print("-" * 40)
print(f"  Total: ${allocated_total:,.2f}")

Use Case 5: Equal Distribution

# Create equal distribution among projects
project_ids = [proj_a_id, proj_b_id, proj_c_id, proj_d_id]

distrib_id = get_model("track.distrib").create({})

# All same ratio = equal percentage
for project_id in project_ids:
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": project_id,
        "ratio": 1,  # Equal ratio
    })

# Each gets 25% (1/4 × 100)

Use Case 6: Weighted Distribution

# Distribution based on headcount
dept_headcounts = {
    sales_track_id: 50,
    engineering_track_id: 30,
    support_track_id: 15,
    admin_track_id: 5,
}

distrib_id = get_model("track.distrib").create({})

for track_id, headcount in dept_headcounts.items():
    get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_id,
        "ratio": headcount,
    })

# Percentages based on headcount:
# Sales: 50% (50/100)
# Engineering: 30% (30/100)
# Support: 15% (15/100)
# Admin: 5% (5/100)

Percentage Calculation

Given distribution with lines:
┌─────────────────┬───────┬──────────────────┐
│ Track Category  │ Ratio │ Percentage       │
├─────────────────┼───────┼──────────────────┤
│ Sales           │   6   │ 6/10 = 60%       │
│ Marketing       │   3   │ 3/10 = 30%       │
│ Support         │   1   │ 1/10 = 10%       │
├─────────────────┼───────┼──────────────────┤
│ Total           │  10   │        100%      │
└─────────────────┴───────┴──────────────────┘

Formula: percent = (ratio / total_ratio) × 100

Best Practices

1. Use Whole Number Ratios

# Good: Clear, understandable ratios
lines = [
    {"ratio": 60},   # 60%
    {"ratio": 30},   # 30%
    {"ratio": 10},   # 10%
]

# Also good: Simple ratios
lines = [
    {"ratio": 3},    # 60%
    {"ratio": 1.5},  # 30%
    {"ratio": 0.5},  # 10%
]

# Less ideal: Complex decimals
lines = [
    {"ratio": 0.6},
    {"ratio": 0.3},
    {"ratio": 0.1},
]

2. Ensure All Lines Have Ratios

# Good: All lines have ratio > 0
for line_data in allocation_data:
    if line_data["ratio"] <= 0:
        raise Exception("Ratio must be greater than 0")
    get_model("track.distrib.line").create(line_data)

3. Validate Before Using

# Verify distribution is complete
lines = get_model("track.distrib.line").search_browse([
    ["distrib_id", "=", distrib_id]
])

if not lines:
    raise Exception("Distribution has no lines")

total_percent = sum(l.percent or 0 for l in lines)
if abs(total_percent - 100) > 0.01:
    print(f"Warning: Distribution totals {total_percent}%, not 100%")

Troubleshooting

"Percent is None"

Cause: Ratio is 0 or total ratio for distribution is 0 Solution: Set ratio > 0 on all lines

"Percentages don't match expected"

Cause: Ratios are relative, not absolute percentages Solution: Ratios determine proportion; system calculates percentage

"Line deleted unexpectedly"

Cause: Parent distribution was deleted (cascade delete) Solution: Expected behavior - lines belong to distribution


Testing Examples

Unit Test: Percentage Calculation

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

    # Create lines with known ratios
    line1_id = get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_a_id,
        "ratio": 3,
    })

    line2_id = get_model("track.distrib.line").create({
        "distrib_id": distrib_id,
        "track_id": track_b_id,
        "ratio": 1,
    })

    # Verify percentages
    line1 = get_model("track.distrib.line").browse([line1_id])[0]
    line2 = get_model("track.distrib.line").browse([line2_id])[0]

    assert line1.percent == 75.0  # 3/4 × 100
    assert line2.percent == 25.0  # 1/4 × 100

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

Unit Test: Equal Distribution

def test_equal_distribution():
    distrib_id = get_model("track.distrib").create({})

    # 4 lines with equal ratio
    track_ids = [track_a_id, track_b_id, track_c_id, track_d_id]
    for track_id in track_ids:
        get_model("track.distrib.line").create({
            "distrib_id": distrib_id,
            "track_id": track_id,
            "ratio": 1,
        })

    # Each should be 25%
    lines = get_model("track.distrib.line").search_browse([
        ["distrib_id", "=", distrib_id]
    ])

    for line in lines:
        assert line.percent == 25.0

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

Security Considerations

Permission Model

  • Line creation requires distribution access
  • Track category access needed for selection

Data Integrity

  • Cascade delete ensures no orphaned lines
  • Required fields prevent incomplete entries

Version History

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


Additional Resources

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

This documentation is generated for developer onboarding and reference purposes.