Sales Dashboard Report Documentation¶
Overview¶
The Sales Dashboard Report module (report.sale) provides comprehensive sales analytics and business intelligence dashboards for the sales management system. This is the master dashboard report that aggregates multiple metrics including sales trends, customer analytics, product performance, opportunity tracking, and revenue forecasting. It serves as the central reporting hub for sales executives and managers.
Model Information¶
Model Name: report.sale
Display Name: Sales Dashboard Report
Type: Non-Stored Report Model
Features¶
- ❌ Not stored in database (
_store = False) - ❌ No persistent fields (dashboard data generated on-demand)
- ✅ Real-time analytics and KPI calculations
- ✅ Multiple dashboard widgets and visualizations
- ✅ Historical trend analysis with time series data
- ✅ Interactive drill-down capabilities
Report Purpose¶
Business Questions Answered¶
The Sales Dashboard Report provides insights to answer:
- Sales Performance: How are sales trending month-over-month?
- Product Analysis: Which products and categories are top sellers?
- Customer Insights: Who are the top revenue-generating customers?
- Pipeline Management: What is the value of opportunities by stage?
- Revenue Forecasting: What is the expected revenue for upcoming periods?
- Customer Acquisition: How many new customers were acquired?
- Conversion Metrics: What is the lead-to-customer conversion rate?
Key Metrics Calculated¶
- Monthly Sales Volume: Total sales amount per month (last 6 months)
- Sales Per Product: Revenue by product (top 5 + others)
- Sales Per Product Category: Revenue by category (top 5 + others)
- Sales Per Customer: Revenue by customer (top 5 + others)
- Opportunity Pipeline Value: Expected revenue by sales stage
- Expected Revenue Forecast: Projected revenue for next 6 months
- New Customer Count: Number of new customers acquired
- New Customer Sales: Total revenue from new customers
- Lead Conversion Rate: Percentage of leads converted to customers
- Daily Sales Cumulative: Day-by-day cumulative sales comparison
Report Methods¶
1. Sales Per Month¶
Method: sales_per_month(context={})
Analyzes sales trends over the past 6 months, showing confirmed and completed orders.
Data Source:
# Query: sale_order table, aggregated by month
# States: 'confirmed', 'done'
# Period: Last 6 months from today
Returns: list - List of tuples (month_name, amount)
Example Output:
[
("October", 150000.00),
("November", 175000.00),
("December", 200000.00),
("January", 165000.00),
("February", 180000.00),
("March", 210000.00)
]
Usage:
# Get monthly sales trend
data = get_model("report.sale").sales_per_month()
# Result: [("October", 150000.00), ("November", 175000.00), ...]
SQL Query:
SELECT to_char(date,'YYYY-MM') AS month,
SUM(amount_total_cur) as amount
FROM sale_order
WHERE state IN ('confirmed','done')
GROUP BY month
2. Sales Per Product¶
Method: sales_per_product(context={})
Identifies top-selling products by revenue, showing the top 5 products individually and grouping the rest as "Other".
Data Source:
# Query: sale_order_line + sale_order + product
# States: 'confirmed', 'done'
# Aggregation: Sum of line amounts by product
Returns: list - List of tuples (product_name, amount)
Example Output:
[
("Premium Widget", 45000.00),
("Standard Widget", 32000.00),
("Deluxe Package", 28000.00),
("Basic Service", 21000.00),
("Pro Service", 18000.00),
("Other", 56000.00) # Sum of all other products
]
Usage:
# Get product performance
products = get_model("report.sale").sales_per_product()
# Display in pie chart or bar graph
SQL Query:
SELECT p.name, SUM(l.amount_cur) as amount
FROM sale_order_line l
JOIN sale_order o ON o.id=l.order_id
JOIN product p ON p.id=l.product_id
WHERE o.state IN ('confirmed','done')
GROUP BY p.name
ORDER BY amount DESC
3. Sales Per Product Category¶
Method: sales_per_product_categ(context={}, month={})
Analyzes sales by product category for a specific month or current month.
Parameters:
- month (str): Date string in YYYY-MM-DD format (defaults to current month)
Returns: list - List of tuples (category_name, amount)
Example Output:
[
("Electronics", 85000.00),
("Software", 62000.00),
("Services", 43000.00),
("Hardware", 28000.00),
("Accessories", 15000.00),
("Other", 32000.00)
]
Usage:
# Get current month category sales
categories = get_model("report.sale").sales_per_product_categ()
# Get specific month
categories = get_model("report.sale").sales_per_product_categ(
month="2026-01-01"
)
SQL Query:
SELECT c.name, SUM(l.amount_cur) as amount
FROM sale_order_line l
JOIN sale_order o ON o.id=l.order_id
JOIN product p ON p.id=l.product_id
JOIN product_categ c ON c.id=p.categ_id
WHERE o.create_time >= '{start_date}'
AND o.create_time <= '{end_date}'
AND o.state IN ('confirmed','done')
GROUP BY c.name
ORDER BY amount DESC
4. Sales Per Customer¶
Method: sales_per_customer(context={})
Identifies top customers by revenue, showing the top 5 customers and grouping others.
Data Source:
# Query: sale_order + contact
# States: 'confirmed', 'done'
# Aggregation: Sum of order totals by customer
Returns: list - List of tuples (customer_name, amount)
Example Output:
[
("ABC Corporation", 125000.00),
("XYZ Industries", 98000.00),
("Tech Solutions Inc", 75000.00),
("Global Enterprises", 62000.00),
("Smart Systems Ltd", 48000.00),
("Other", 192000.00)
]
Usage:
# Get top customers
customers = get_model("report.sale").sales_per_customer()
# Use for customer segmentation analysis
SQL Query:
SELECT c.name, SUM(o.amount_total) as amount
FROM sale_order o
JOIN contact c ON c.id=o.contact_id
WHERE o.state IN ('confirmed','done')
GROUP BY c.name
ORDER BY amount DESC
5. Opportunity Stage Analysis¶
Method: opport_stage(context={})
Analyzes sales opportunities by stage, calculating weighted value based on probability.
Data Source:
# Query: sale_opportunity + sale_stage
# States: 'open', 'won'
# Calculation: amount * probability / 100
Returns: list - List of tuples (stage_name, weighted_amount)
Example Output:
[
("Lead", 15000.00), # 50 opps × 30% probability
("Qualified", 42000.00), # 35 opps × 60% probability
("Proposal", 68000.00), # 20 opps × 80% probability
("Negotiation", 85000.00), # 15 opps × 90% probability
("Won", 120000.00) # 12 opps × 100%
]
Usage:
# Get opportunity pipeline value
pipeline = get_model("report.sale").opport_stage()
# Display in funnel chart
SQL Query:
SELECT s.name,
SUM(o.amount*o.probability/100) AS amount,
COUNT(*) AS num
FROM sale_opportunity o
JOIN sale_stage s ON s.id=o.stage_id
WHERE o.state IN ('open','won')
GROUP BY s.name
6. Expected Revenue Forecast¶
Method: expected_revenue(context={})
Projects expected revenue for the next 6 months based on opportunity close dates and probabilities.
Data Source:
# Query: sale_opportunity
# States: 'open', 'won'
# Period: Next 6 months + future
# Calculation: amount * probability / 100
Returns: list - List of tuples (month_abbrev, projected_amount)
Example Output:
[
("Jan", 145000.00),
("Feb", 132000.00),
("Mar", 168000.00),
("Apr", 155000.00),
("May", 178000.00),
("Jun", 162000.00),
("Future", 245000.00) # Beyond 6 months
]
Usage:
# Get revenue forecast
forecast = get_model("report.sale").expected_revenue()
# Use for budgeting and capacity planning
SQL Query:
SELECT date_trunc('month',o.date_close) AS month,
SUM(o.amount*o.probability/100),
COUNT(*)
FROM sale_opportunity o
WHERE o.state IN ('open','won')
GROUP BY month
7. Sales Per Day (Cumulative)¶
Method: get_sales_per_day(context={}, month={})
Compares cumulative daily sales for current month vs previous month.
Parameters:
- month (str): Date string in YYYY-MM-DD format for the month to analyze
Returns: list - List of series dictionaries for charting
Example Output:
[
{
"name": "This Month",
"data": [[1, 5000], [2, 12000], [3, 18000], ..., [15, 185000]],
"color": "blue"
},
{
"name": "Previous Month",
"data": [[1, 4500], [2, 10000], [3, 15500], ..., [15, 165000]],
"color": "orange"
}
]
Usage:
# Get daily sales comparison
daily_sales = get_model("report.sale").get_sales_per_day(
month="2026-01-01"
)
# Display in line chart to show growth trends
Behavior: - Calculates cumulative total day by day - Compares same day-of-month between periods - Returns data suitable for line chart visualization - Useful for identifying sales acceleration or deceleration
8. New Customer Acquisition¶
Method: get_new_customer(context={}, month={})
Counts new customers acquired in a specific month.
Parameters:
- month (str): Date string in YYYY-MM-DD format (defaults to current month)
Returns: list - List with single metric dictionary
Example Output:
Usage:
# Get new customers this month
new_customers = get_model("report.sale").get_new_customer()
# Get new customers for specific month
new_customers = get_model("report.sale").get_new_customer(
month="2026-01-01"
)
# Result: [{"name": "New Customer", "data": 23, "color": "blue"}]
SQL Query:
9. New Customer Sales¶
Method: get_sale_new_customer(context={}, month={})
Calculates total sales from customers acquired in a specific month.
Parameters:
- month (str): Date string in YYYY-MM-DD format (defaults to current month)
Returns: list - List with single metric dictionary
Example Output:
Usage:
# Get sales from new customers this month
new_cust_sales = get_model("report.sale").get_sale_new_customer()
# Get sales from specific month's new customers
new_cust_sales = get_model("report.sale").get_sale_new_customer(
month="2026-01-01"
)
Behavior: - Identifies customers created in specified month - Sums all their sales orders (all time, not just that month) - Useful for measuring customer acquisition quality - Helps calculate customer lifetime value for cohorts
10. Lead Conversion Rate¶
Method: get_conversion(context={}, month={})
Calculates the lead-to-customer conversion rate over the last 12 months.
Parameters:
- month (str): End date for 12-month lookback period
Returns: list - List with single metric dictionary
Example Output:
Usage:
# Get conversion rate
conversion = get_model("report.sale").get_conversion()
# Result: [{"name": "Last 12 month conversion", "data": 34.57, ...}]
Calculation:
Business Insight: - Higher percentage indicates better lead quality - Lower percentage may indicate need for lead qualification improvements - Benchmark against industry standards
11. Monthly Sales Total¶
Method: monthly_sale(context={}, month={})
Calculates total sales for a specific month.
Parameters:
- month (str): Date string in YYYY-MM-DD format (defaults to current month)
Returns: list - List with single metric dictionary
Example Output:
Usage:
# Get current month sales
monthly_total = get_model("report.sale").monthly_sale()
# Get specific month sales
monthly_total = get_model("report.sale").monthly_sale(
month="2026-01-01"
)
SQL Query:
SELECT SUM(amount_total_cur) as amount
FROM sale_order
WHERE create_time >= '{month_start}'
AND create_time <= '{month_end}'
Helper Functions¶
get_past_months(num_months)¶
Purpose: Generates list of past month/year tuples for time series analysis.
Parameters:
- num_months (int): Number of months to generate
Returns: list - Reversed list of (year, month) tuples
Example:
# Called in January 2026
result = get_past_months(6)
# Returns: [(2025, 8), (2025, 9), (2025, 10), (2025, 11), (2025, 12), (2026, 1)]
get_future_months(num_months)¶
Purpose: Generates list of future month/year tuples for forecasting.
Parameters:
- num_months (int): Number of months to generate
Returns: list - List of (year, month) tuples
Example:
# Called in January 2026
result = get_future_months(6)
# Returns: [(2026, 1), (2026, 2), (2026, 3), (2026, 4), (2026, 5), (2026, 6)]
Data Sources¶
Primary Models Queried¶
| Model | Usage | Join Keys |
|---|---|---|
sale.order |
Main sales transactions | id |
sale.order.line |
Product-level detail | order_id → sale.order.id |
product |
Product information | id ← sale.order.line.product_id |
product.categ |
Product categories | id ← product.categ_id |
contact |
Customer information | id ← sale.order.contact_id |
sale.opportunity |
Sales pipeline | id |
sale.stage |
Opportunity stages | id ← sale.opportunity.stage_id |
sale.lead |
Lead tracking | id |
Dashboard Visualizations¶
Recommended Charts¶
- Monthly Sales Trend
- Type: Line Chart
- Data:
sales_per_month() -
Purpose: Show sales trajectory over time
-
Product Performance
- Type: Pie Chart or Bar Chart
- Data:
sales_per_product() -
Purpose: Identify best-selling products
-
Category Analysis
- Type: Donut Chart
- Data:
sales_per_product_categ() -
Purpose: Category revenue distribution
-
Top Customers
- Type: Horizontal Bar Chart
- Data:
sales_per_customer() -
Purpose: Customer segmentation
-
Sales Funnel
- Type: Funnel Chart
- Data:
opport_stage() -
Purpose: Pipeline visualization
-
Revenue Forecast
- Type: Column Chart
- Data:
expected_revenue() -
Purpose: Future revenue projection
-
Daily Sales Comparison
- Type: Multi-Line Chart
- Data:
get_sales_per_day() -
Purpose: Period-over-period comparison
-
KPI Metrics
- Type: Metric Cards
- Data:
monthly_sale(),get_new_customer(),get_conversion() - Purpose: Key performance indicators
Common Use Cases¶
Use Case 1: Executive Sales Dashboard¶
# Generate comprehensive executive dashboard
# 1. Get monthly sales trend (6 months)
monthly_trend = get_model("report.sale").sales_per_month()
# 2. Get current month metrics
current_month = date.today().strftime("%Y-%m-01")
monthly_total = get_model("report.sale").monthly_sale(month=current_month)
new_customers = get_model("report.sale").get_new_customer(month=current_month)
new_cust_revenue = get_model("report.sale").get_sale_new_customer(month=current_month)
# 3. Get product and customer insights
top_products = get_model("report.sale").sales_per_product()
top_customers = get_model("report.sale").sales_per_customer()
# 4. Get pipeline and forecast
pipeline = get_model("report.sale").opport_stage()
forecast = get_model("report.sale").expected_revenue()
# 5. Get conversion metrics
conversion_rate = get_model("report.sale").get_conversion()
# Display all in unified dashboard
dashboard_data = {
"kpis": {
"monthly_sales": monthly_total[0]["data"],
"new_customers": new_customers[0]["data"],
"new_customer_revenue": new_cust_revenue[0]["data"],
"conversion_rate": conversion_rate[0]["data"]
},
"trends": {
"monthly": monthly_trend,
"products": top_products,
"customers": top_customers
},
"pipeline": {
"stages": pipeline,
"forecast": forecast
}
}
Use Case 2: Month-over-Month Performance Analysis¶
# Compare current month with previous month
from datetime import date
from dateutil.relativedelta import relativedelta
# Current month
current_month = date.today().strftime("%Y-%m-01")
current_sales = get_model("report.sale").monthly_sale(month=current_month)
current_customers = get_model("report.sale").get_new_customer(month=current_month)
# Previous month
prev_month_date = date.today() - relativedelta(months=1)
prev_month = prev_month_date.strftime("%Y-%m-01")
prev_sales = get_model("report.sale").monthly_sale(month=prev_month)
prev_customers = get_model("report.sale").get_new_customer(month=prev_month)
# Calculate growth
sales_growth = ((current_sales[0]["data"] - prev_sales[0]["data"])
/ prev_sales[0]["data"] * 100)
customer_growth = ((current_customers[0]["data"] - prev_customers[0]["data"])
/ prev_customers[0]["data"] * 100)
print(f"Sales Growth: {sales_growth:.2f}%")
print(f"Customer Growth: {customer_growth:.2f}%")
# Get daily comparison for detailed analysis
daily_comparison = get_model("report.sale").get_sales_per_day(month=current_month)
Use Case 3: Product Category Performance Review¶
# Analyze product category performance for current month
current_month = date.today().strftime("%Y-%m-01")
# Get category sales for current month
category_sales = get_model("report.sale").sales_per_product_categ(
month=current_month
)
# Get product-level detail
product_sales = get_model("report.sale").sales_per_product()
# Calculate category metrics
total_sales = sum(amount for _, amount in category_sales)
category_analysis = []
for category_name, amount in category_sales:
percentage = (amount / total_sales * 100) if total_sales > 0 else 0
category_analysis.append({
"category": category_name,
"revenue": amount,
"percentage": percentage
})
# Display sorted by revenue
for cat in sorted(category_analysis, key=lambda x: x["revenue"], reverse=True):
print(f"{cat['category']}: ${cat['revenue']:,.2f} ({cat['percentage']:.1f}%)")
Use Case 4: Sales Pipeline Health Check¶
# Analyze sales pipeline health and conversion
# Get opportunity distribution by stage
pipeline = get_model("report.sale").opport_stage()
# Get expected revenue forecast
forecast = get_model("report.sale").expected_revenue()
# Calculate pipeline metrics
total_pipeline_value = sum(amount for _, amount in pipeline)
next_month_forecast = forecast[0][1] if forecast else 0
# Calculate coverage ratio
current_month_sales = get_model("report.sale").monthly_sale()
current_sales_amount = current_month_sales[0]["data"]
pipeline_coverage = (total_pipeline_value / current_sales_amount
if current_sales_amount > 0 else 0)
print(f"Total Pipeline Value: ${total_pipeline_value:,.2f}")
print(f"Current Month Sales: ${current_sales_amount:,.2f}")
print(f"Pipeline Coverage Ratio: {pipeline_coverage:.2f}x")
print(f"Next Month Forecast: ${next_month_forecast:,.2f}")
# Alert if pipeline coverage is low
if pipeline_coverage < 3.0:
print("⚠️ WARNING: Pipeline coverage below 3x threshold!")
Use Case 5: Customer Acquisition Analysis¶
# Analyze customer acquisition effectiveness
current_month = date.today().strftime("%Y-%m-01")
# Get new customer metrics
new_customers = get_model("report.sale").get_new_customer(month=current_month)
new_customer_sales = get_model("report.sale").get_sale_new_customer(month=current_month)
# Get conversion rate
conversion_data = get_model("report.sale").get_conversion()
# Calculate average revenue per new customer
num_new_customers = new_customers[0]["data"]
total_new_cust_sales = new_customer_sales[0]["data"]
avg_revenue_per_new_customer = (total_new_cust_sales / num_new_customers
if num_new_customers > 0 else 0)
conversion_rate = conversion_data[0]["data"]
print(f"New Customers Acquired: {num_new_customers}")
print(f"Revenue from New Customers: ${total_new_cust_sales:,.2f}")
print(f"Average Revenue per New Customer: ${avg_revenue_per_new_customer:,.2f}")
print(f"Lead Conversion Rate: {conversion_rate:.2f}%")
# Calculate customer acquisition cost effectiveness
# (Assuming marketing spend is tracked separately)
marketing_spend = 15000 # Example
cost_per_acquisition = marketing_spend / num_new_customers if num_new_customers > 0 else 0
customer_lifetime_value_ratio = avg_revenue_per_new_customer / cost_per_acquisition
print(f"Cost per Acquisition: ${cost_per_acquisition:,.2f}")
print(f"CLV/CAC Ratio: {customer_lifetime_value_ratio:.2f}x")
Performance Tips¶
1. Optimize Date Range Queries¶
# Bad: Querying all time then filtering in Python
all_orders = get_model("sale.order").search_browse([])
recent_orders = [o for o in all_orders if o.date >= start_date]
# Good: Filter at database level (done by report methods)
# The report methods already apply date filters in SQL
monthly_sales = get_model("report.sale").monthly_sale(month="2026-01-01")
2. Cache Dashboard Data¶
# For frequently accessed dashboards, cache the results
from functools import lru_cache
from datetime import datetime
@lru_cache(maxsize=128)
def get_cached_dashboard(date_key):
"""Cache dashboard data for 1 hour"""
return {
"monthly_sales": get_model("report.sale").monthly_sale(),
"top_products": get_model("report.sale").sales_per_product(),
"top_customers": get_model("report.sale").sales_per_customer(),
"timestamp": datetime.now()
}
# Use with hourly cache key
cache_key = datetime.now().strftime("%Y-%m-%d-%H")
dashboard = get_cached_dashboard(cache_key)
3. Batch Multiple Report Calls¶
# When generating comprehensive reports, batch data retrieval
def get_full_dashboard_data(month=None):
"""Get all dashboard data in one function to minimize overhead"""
if month is None:
month = date.today().strftime("%Y-%m-01")
report_model = get_model("report.sale")
# Fetch all data
data = {
"monthly_trend": report_model.sales_per_month(),
"monthly_total": report_model.monthly_sale(month=month),
"products": report_model.sales_per_product(),
"categories": report_model.sales_per_product_categ(month=month),
"customers": report_model.sales_per_customer(),
"pipeline": report_model.opport_stage(),
"forecast": report_model.expected_revenue(),
"new_customers": report_model.get_new_customer(month=month),
"new_cust_sales": report_model.get_sale_new_customer(month=month),
"conversion": report_model.get_conversion(),
"daily_comparison": report_model.get_sales_per_day(month=month)
}
return data
# Single call gets all dashboard data
dashboard = get_full_dashboard_data()
Related Models¶
| Model | Relationship | Description |
|---|---|---|
sale.order |
Data Source | Main transaction records queried for sales metrics |
sale.order.line |
Data Source | Line-level product sales data |
product |
Data Source | Product information for analytics |
product.categ |
Data Source | Product categorization |
contact |
Data Source | Customer information |
sale.opportunity |
Data Source | Sales pipeline and forecast data |
sale.stage |
Data Source | Opportunity stage definitions |
sale.lead |
Data Source | Lead tracking for conversion metrics |
report.sale.order |
Related Report | Detailed product sales report |
report.sale.profit |
Related Report | Profitability analysis report |
report.sale.commission |
Related Report | Commission calculations |
Best Practices¶
1. Use Appropriate Time Periods¶
# Bad: Requesting data without time boundaries
all_time_data = get_model("report.sale").sales_per_product() # Could be slow
# Good: Use time-bounded methods or specify periods
monthly_data = get_model("report.sale").sales_per_product_categ(
month="2026-01-01"
)
# For custom periods, query sale.order directly with filters
cond = [
["date", ">=", "2026-01-01"],
["date", "<=", "2026-03-31"],
["state", "in", ["confirmed", "done"]]
]
quarterly_orders = get_model("sale.order").search_browse(cond)
2. Interpret "Other" Category Correctly¶
# The "Other" category aggregates items beyond top 5
# To see detail, query the data source directly
products = get_model("report.sale").sales_per_product()
# To see all products (not just top 5):
cond = [["order_id.state", "in", ["confirmed", "done"]]]
all_lines = get_model("sale.order.line").search_browse(cond)
product_sales = {}
for line in all_lines:
prod_name = line.product_id.name if line.product_id else "Unknown"
product_sales.setdefault(prod_name, 0)
product_sales[prod_name] += line.amount_cur or 0
# Sort and display all
for prod, amt in sorted(product_sales.items(), key=lambda x: x[1], reverse=True):
print(f"{prod}: ${amt:,.2f}")
3. Validate Data Consistency¶
# Cross-check dashboard totals against source data
# Get monthly total from dashboard
dashboard_total = get_model("report.sale").monthly_sale(month="2026-01-01")
# Verify against direct query
cond = [
["create_time", ">=", "2026-01-01 00:00:00"],
["create_time", "<=", "2026-01-31 23:59:59"]
]
orders = get_model("sale.order").search_browse(cond)
actual_total = sum(o.amount_total_cur for o in orders)
# Compare
dashboard_amt = dashboard_total[0]["data"]
difference = abs(dashboard_amt - actual_total)
if difference > 0.01: # Allow for rounding
print(f"⚠️ Data inconsistency detected!")
print(f"Dashboard: ${dashboard_amt:,.2f}")
print(f"Actual: ${actual_total:,.2f}")
Troubleshooting¶
"No data returned for sales_per_day"¶
Cause: The month parameter is not provided, and there's a return statement when month is None.
Solution: Always provide the month parameter:
# Bad
daily_sales = get_model("report.sale").get_sales_per_day() # Returns None
# Good
daily_sales = get_model("report.sale").get_sales_per_day(
month=date.today().strftime("%Y-%m-01")
)
"Division by zero in conversion calculation"¶
Cause: No customers exist in the 12-month period, causing division by zero.
Solution: The model handles this internally, but you should validate:
conversion = get_model("report.sale").get_conversion()
if conversion and conversion[0]["data"] > 0:
rate = conversion[0]["data"]
else:
rate = 0.0
print("No conversion data available")
"Unexpected data format from report method"¶
Cause: Different methods return different data structures (list of tuples vs list of dicts).
Solution: Check the return type for each method:
# Returns list of tuples
monthly_sales = get_model("report.sale").sales_per_month()
# Usage: for month_name, amount in monthly_sales:
# Returns list of dicts
monthly_total = get_model("report.sale").monthly_sale()
# Usage: monthly_total[0]["data"]
Integration Points¶
Dashboard Integration¶
Display dashboard data in web UI:
# In controller/view
def get_sales_dashboard(request):
report = get_model("report.sale")
data = {
"monthly_sales": report.monthly_sale(),
"new_customers": report.get_new_customer(),
"top_products": report.sales_per_product(),
"pipeline": report.opport_stage()
}
return render("sales_dashboard.html", data)
Export to Excel¶
import xlsxwriter
def export_dashboard_to_excel(filename):
workbook = xlsxwriter.Workbook(filename)
# Monthly sales sheet
ws_monthly = workbook.add_worksheet("Monthly Sales")
monthly_data = get_model("report.sale").sales_per_month()
ws_monthly.write(0, 0, "Month")
ws_monthly.write(0, 1, "Amount")
for idx, (month, amount) in enumerate(monthly_data, start=1):
ws_monthly.write(idx, 0, month)
ws_monthly.write(idx, 1, amount)
# Products sheet
ws_products = workbook.add_worksheet("Top Products")
product_data = get_model("report.sale").sales_per_product()
ws_products.write(0, 0, "Product")
ws_products.write(0, 1, "Amount")
for idx, (product, amount) in enumerate(product_data, start=1):
ws_products.write(idx, 0, product)
ws_products.write(idx, 1, amount)
workbook.close()
# Export dashboard
export_dashboard_to_excel("sales_dashboard.xlsx")
Version History¶
Last Updated: 2026-01-05 Model Version: report_sale.py Framework: Netforce
Additional Resources¶
- Sales Order Documentation:
sale.order - Opportunity Management Documentation:
sale.opportunity - Product Analytics:
report.sale.order - Profit Analysis:
report.sale.profit - Commission Reports:
report.sale.commission
Support & Feedback¶
For issues or questions about this module: 1. Verify sale orders have correct states ('confirmed' or 'done') 2. Check date ranges are properly formatted (YYYY-MM-DD) 3. Ensure products and customers are properly linked 4. Review database query logs for performance issues
This documentation is generated for developer onboarding and reference purposes.