Sales Profit Details Report Documentation¶
Overview¶
The Sales Profit Details Report module (report.sale.profit.details) provides line-item drill-down analysis for a specific sales order, showing cost, pricing, and profit margins for each product/service line. This is the detail companion to report.sale.profit.
Model Information¶
Model Name: report.sale.profit.details
Display Name: Sales Profit Details Report
Type: Transient Report Model (_transient = True)
Features¶
- Line-by-line profit breakdown for a single order
- Product description and quantities
- Unit price and total amount per line
- Cost price and total cost per line
- Links to parent profit summary report
Key Fields Reference¶
Report Parameters¶
| Field | Type | Required | Description |
|---|---|---|---|
sale_id |
Many2One | Yes | Sales order to analyze (required for detail view) |
Output Fields¶
| Field | Description |
|---|---|
sequence |
Line sequence/description |
description |
Product/service description |
qty |
Quantity ordered |
uom_name |
Unit of measure |
unit_price |
Unit selling price |
amount |
Line total (unit_price * qty) |
cost_price |
Unit cost price |
cost_amount |
Line total cost (cost_price * qty) |
API Methods¶
1. Generate Detail Report¶
Method: get_report_data(ids, context)
Generates line-item profit details for a specific order.
Parameters:
Returns: dict - Report data:
{
"company_name": "ABC Company",
"order_number": "SO-2024-001",
"lines": [
{
"sequence": "Product XYZ",
"description": "Product XYZ - Premium Quality",
"qty": 10,
"uom_name": "Unit",
"unit_price": 150.00,
"amount": 1500.00,
"cost_price": 100.00,
"cost_amount": 1000.00
}
]
}
Example:
# Generate detail report for specific order
sale_order_id = 123
detail_report_id = get_model("report.sale.profit.details").create({
"sale_id": sale_order_id
})
data = get_model("report.sale.profit.details").get_report_data([detail_report_id])
print(f"Profit Details for Order {data['order_number']}:")
for line in data["lines"]:
line_profit = line["amount"] - line.get("cost_amount", 0)
line_margin = (line_profit / line["amount"]) * 100 if line["amount"] else 0
print(f" {line['description']}: ${line['amount']:,.2f} - Margin {line_margin:.1f}%")
Related Models¶
| Model | Relationship | Description |
|---|---|---|
sale.order |
Required Parent | Sales order being analyzed |
sale.order.line |
Data Source | Order lines with pricing and costs |
report.sale.profit |
Parent Report | Summary-level profit report |
Common Use Cases¶
Use Case 1: Line-Item Profitability Review¶
# Analyze which products in an order are most/least profitable
sale_order_id = 456
report_id = get_model("report.sale.profit.details").create({
"sale_id": sale_order_id
})
data = get_model("report.sale.profit.details").get_report_data([report_id])
# Calculate margin for each line
line_analysis = []
for line in data["lines"]:
if line.get("amount") and line.get("cost_amount") is not None:
profit = line["amount"] - line["cost_amount"]
margin = (profit / line["amount"]) * 100 if line["amount"] else 0
line_analysis.append({
"product": line["description"],
"qty": line["qty"],
"revenue": line["amount"],
"cost": line["cost_amount"],
"profit": profit,
"margin": margin
})
# Sort by margin
line_analysis.sort(key=lambda x: x["margin"])
print("Line Items by Margin (Low to High):")
for item in line_analysis:
print(f"{item['product']}: {item['margin']:.1f}% margin (Profit: ${item['profit']:,.2f})")
Use Case 2: Integrated Summary-to-Detail Flow¶
# Start with summary, drill down on low-margin orders
# 1. Generate summary
summary_id = get_model("report.sale.profit").create({
"date_from": "2024-01-01",
"date_to": "2024-01-31"
})
summary_data = get_model("report.sale.profit").get_report_data([summary_id])
# 2. Find orders with margins < 20%
low_margin_orders = [
line for line in summary_data["lines"]
if line.get("act_profit_percent", 0) < 20
]
print(f"Found {len(low_margin_orders)} orders with margins < 20%\n")
# 3. Drill down into each
for order in low_margin_orders:
detail_id = get_model("report.sale.profit.details").create({
"sale_id": order["id"]
})
detail_data = get_model("report.sale.profit.details").get_report_data([detail_id])
print(f"Order {order['number']} - {order['customer']}:")
print(f" Overall Margin: {order.get('act_profit_percent', 0):.1f}%")
print(" Line Items:")
for line in detail_data["lines"]:
if line.get("amount"):
line_profit = line["amount"] - line.get("cost_amount", 0)
line_margin = (line_profit / line["amount"]) * 100
print(f" - {line['description']}: {line_margin:.1f}% margin")
print()
Use Case 3: Product Pricing Review¶
# Review pricing vs cost across multiple orders for a product
product_name = "Widget Pro"
# Find orders containing this product
orders = get_model("sale.order").search_browse([
["lines.product_id.name", "=", product_name],
["date", ">=", "2024-01-01"]
])
product_pricing = []
for order in orders:
detail_id = get_model("report.sale.profit.details").create({
"sale_id": order.id
})
data = get_model("report.sale.profit.details").get_report_data([detail_id])
# Find the product line
product_line = next((l for l in data["lines"] if product_name in l.get("description", "")), None)
if product_line and product_line.get("amount"):
margin = ((product_line["amount"] - product_line.get("cost_amount", 0)) / product_line["amount"]) * 100
product_pricing.append({
"order": order.number,
"customer": order.contact_id.name,
"qty": product_line["qty"],
"unit_price": product_line["unit_price"],
"cost_price": product_line.get("cost_price", 0),
"margin": margin
})
print(f"Pricing Analysis for {product_name}:")
for pricing in product_pricing:
print(f"{pricing['order']} - {pricing['customer']}:")
print(f" Price: ${pricing['unit_price']:,.2f}, Cost: ${pricing['cost_price']:,.2f}, Margin: {pricing['margin']:.1f}%")
Performance Tips¶
1. Single Order Focus¶
- This report is designed for single order analysis
- Don't iterate through all orders in a loop (use summary report instead)
- Use summary report to identify orders worth drilling into
2. Efficient Workflow¶
# Good: Selective drill-down
summary_report -> identify problem orders -> detail report for each
# Bad: Drill into every order
for order in all_orders: # Don't do this
generate_detail_report(order.id)
Troubleshooting¶
"No sale_id provided"¶
Cause: Detail report requires a specific sale order ID
Solution:
- Always provide sale_id parameter when creating report
- Get sale_id from summary report or order search
"Cost amounts missing"¶
Cause: Order lines don't have cost_price populated Solution: - Ensure products have cost prices configured - Check if cost calculation is set up correctly - Cost may be unavailable for service items
Version History¶
Last Updated: 2026-01-05 Model Version: report_sale_profit_details.py (47 lines) Framework: Netforce
Additional Resources¶
- Summary Report Documentation:
report.sale.profit - Sales Order Documentation:
sale.order
This documentation is generated for developer onboarding and reference purposes.