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:
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%
Related Models¶
| 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.