Script Report Automatically Treated as Prepared Report (Even When Not Wanted)

Hi everyone,

I’m facing an issue with a custom Script Report in Frappe.

Even though:

  • My execute function only returns columns, data (not "Prepared Report"),
  • The “Is Prepared Report” option is unchecked in the Report DocType,
  • The report type is correctly set to “Script Report”,

Frappe still automatically treats it as a Prepared Report, which I don’t want.
I need the report to run instantly/synchronously, regardless of how many rows it returns.

Any idea what might be forcing this behavior?
Thanks in advance for any help! :pray:

@Hela_Guesmi check this Why is 'Prepared Report' Button Auto-Enabled in Frappe v15?
Script Report automatically converted to prepared report · Issue #31362 · frappe/frappe · GitHub
[Solved] How do Prepared Reports "Actually" work?!? - #6 by bkm

1 Like

Check out this

@SanaullaHaq please explain it properly

The problem that the Reports with large datasets are taking too long to load, causing them to automatically switch to “Prepared Report” mode.

Root Cause: This behavior is controlled by a time threshold in the Frappe framework. If a report’s execution time exceeds this threshold, the system defaults to a prepared report.

Solution: Increase the execution time threshold.

File to Modify: frappe/frappe/core/doctype/report/report.py

Locate the execute_script_report() function and find the threshold variable. Increase its value (in seconds).

# Change this line:
threshold = 15

# To a higher value, for example 30 or more :
threshold = 30
1 Like

Changing the core is not a solution in my mind. Here is another option. In the report_name.py file add the following method:

@frappe.whitelist()
def reset_prepared_report():
    """Clear report runtime cache."""
    frappe.db.set_value(
        "Report",
        "Report Name",
        "prepared_report",
        0
    )
    frappe.db.commit()
    frappe.cache.hset("report_execution_time", "Report Name", 1)

Then in the report_name.js file add the following:

frappe.query_reports["Report Name"] = {
    filters: [
       ...
    ],
	after_datatable_render: function (datatable_obj) {
		frappe.call({
			method: "path_to_report.reset_prepared_report",
		});
	},
};

After the data table is rendered, the reset_prepared_report method is called, which does 2 things:

  1. Updates the report to not be a prepared report any longer.
  2. Change the cache for the report execution time to 1 second.

The second step is important otherwise the next time you run the report the dialog box appears for “Preparing report”.

1 Like