Script Reports in iVendNext are the most advanced reporting option, allowing users to execute Python-based logic for data processing, complex calculations, and customized analytics. Unlike Report Builder or Query Reports, Script Reports are stored on the server and support dynamic filters, conditional formatting, and multi-dataset operations.
This guide explains how Script Reports work, their ideal use cases, and how administrators can create or modify them (note: not customizable for cloud users).
Script Reports are Python-driven reports that:
✔ Perform calculations (e.g., financial ratios, inventory forecasting).
✔ Combine data from multiple tables or modules.
✔ Support dynamic filters and conditional logic.
Example: The "Financial Analytics" report in the Accounts module is a Script Report.
Key Limitation:
Script Reports cannot be edited in hosted/cloud environments due to server-side restrictions. Only on-premise users or developers can modify them.
A Script Report consists of:
Fetches data using frappe.db.sql or frappe.get_all.
Processes data with Pandas, NumPy, or custom functions.
Defined as a filters dictionary for user input.
Returns data as a list of dictionaries for HTML/PDF rendering.
Go to Customize > Report > New Report.
Select Report Type: Script Report.
Example: A report calculating profit margins by item:
import frappe
def execute(filters=None):
columns = [
{"label": "Item", "fieldname": "item", "fieldtype": "Link", "options": "Item"},
{"label": "Profit Margin (%)", "fieldname": "margin", "fieldtype": "Percent"}
]
data = frappe.db.sql("""
SELECT
item.item_code AS item,
(SUM(sales.amount) - SUM(sales.cost)) / SUM(sales.amount) * 100 AS margin
FROM `tabSales Invoice Item` sales
JOIN `tabItem` item ON sales.item_code = item.name
WHERE sales.posting_date BETWEEN %(from_date)s AND %(to_date)s
GROUP BY item.item_code
""", filters, as_dict=1)
return columns, data
Add interactive filters in the filters dictionary:
filters = [
{
"fieldname": "from_date",
"label": "From Date",
"fieldtype": "Date",
"default": frappe.utils.add_months(frappe.utils.nowdate(), -1)
},
{
"fieldname": "to_date",
"label": "To Date",
"fieldtype": "Date",
"default": frappe.utils.nowdate()
}
]
Click Save.
Run the report with test filters to validate results.
Highlight rows based on rules (e.g., red for negative margins):
for row in data:
row["margin_color"] = "red" if row["margin"] < 0 else "green"
Combine data from multiple queries:
sales_data = frappe.db.sql("""SELECT ...""", filters)
purchase_data = frappe.db.sql("""SELECT ...""", filters)
Fetch real-time data (e.g., currency rates):
import requests
response = requests.get("https://api.exchangerate.host/latest")
Cause: Missing Python library (e.g., Pandas).
Fix: Install the package on the server or use Frappe’s built-in utilities.
Causes:
Unoptimized SQL queries.
Heavy calculations in loops.
Fix:
Use INDEXES in database tables.
Limit fetched data with WHERE clauses.
Cause: The user lacks access to referenced DocTypes.
Fix: Update role permissions via Customize > Permissions.
Sanitize Inputs: Always pass filters via %(...)s placeholders.
Restrict Access: Grant Script Report permissions only to trusted roles.
Avoid Hardcoding Secrets: Use Frappe’s Config for API keys.
Script Reports unlock iVendNext’s full analytical potential but require Python expertise. They are ideal for:
Financial modeling.
Custom dashboards.
Real-time data integrations.