Merge pull request #32733 from iamejaaz/json-to-csv-prepared

feat: add download as csv option in prepared report
This commit is contained in:
Ejaaz Khan 2025-06-03 14:45:11 +05:30 committed by GitHub
commit 7d4e703318
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 92 additions and 4 deletions

View file

@ -44,6 +44,24 @@ frappe.ui.form.on("Prepared Report", {
frappe.route_options = { prepared_report_name: frm.doc.name };
frappe.set_route("query-report", frm.doc.report_name);
});
let csv_attached = (frm.get_files() || []).some((f) => f.file_url.endsWith(".csv"));
if (!csv_attached) {
frm.add_custom_button(__("Download as CSV"), function () {
frappe.call({
method: "frappe.core.doctype.prepared_report.prepared_report.enqueue_json_to_csv_conversion",
args: {
prepared_report_name: frm.doc.name,
},
callback: function () {
frappe.msgprint(
__(
"Your CSV file is being generated and will appear in the Attachments section once ready. Additionally, you will get notified when the file is available for download."
)
);
},
});
});
}
}
},
});

View file

@ -85,7 +85,12 @@ class PreparedReport(Document):
def get_prepared_data(self, with_file_name=False):
if attachments := get_attachments(self.doctype, self.name):
attachment = attachments[0]
attachment = None
for f in attachments or []:
if f.file_url.endswith(".gz"):
attachment = f
break
attached_file = frappe.get_doc("File", attachment.name)
if with_file_name:
@ -297,3 +302,67 @@ def has_permission(doc, user):
return True
return doc.report_name in user.get_all_reports().keys()
@frappe.whitelist()
def enqueue_json_to_csv_conversion(prepared_report_name):
"""Call this to enqueue the conversion in background."""
enqueue(method=convert_json_to_csv, queue="long", prepared_report_name=prepared_report_name)
def convert_json_to_csv(prepared_report_name):
"""Background job: Fetch JSON file, convert to CSV, attach CSV to Prepared Report."""
import csv
from io import StringIO
doc = frappe.get_doc("Prepared Report", prepared_report_name)
json_content, file_name = doc.get_prepared_data(with_file_name=True)
if not json_content:
frappe.log_error(f"No JSON content found for {prepared_report_name}", "CSV Conversion")
return
parsed = json.loads(json_content)
columns = parsed.get("columns", [])
result = parsed.get("result", [])
if not columns or not result:
frappe.log_error("Columns or result is empty", "CSV Conversion")
return
fieldnames = [col.get("fieldname") for col in columns if col.get("fieldname")]
output = StringIO()
writer = csv.DictWriter(output, fieldnames=fieldnames)
writer.writeheader()
for row in result:
writer.writerow({key: row.get(key, "") for key in fieldnames})
csv_content = output.getvalue().encode("utf-8")
_file = frappe.get_doc(
{
"doctype": "File",
"file_name": f"csv_{file_name[:-8]}.csv",
"attached_to_doctype": "Prepared Report",
"attached_to_name": prepared_report_name,
"content": csv_content,
"is_private": 1,
}
)
_file.save(ignore_permissions=True)
frappe.get_doc(
{
"doctype": "Notification Log",
"subject": "Your CSV file is ready for download",
"email_content": f'Click <a href="{_file.file_url}" target="_blank">here</a> to download the file.',
"for_user": frappe.session.user,
"type": "Alert",
"document_type": "File",
"document_name": _file.name,
"link": _file.file_url,
}
).insert(ignore_permissions=True)

View file

@ -96,7 +96,7 @@
},
{
"fieldname": "link",
"fieldtype": "Data",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Link"
},
@ -109,7 +109,7 @@
"hide_toolbar": 1,
"in_create": 1,
"links": [],
"modified": "2025-05-10 23:58:54.717673",
"modified": "2025-05-30 20:17:44.969738",
"modified_by": "Administrator",
"module": "Desk",
"name": "Notification Log",

View file

@ -24,9 +24,10 @@ class NotificationLog(Document):
document_name: DF.Data | None
document_type: DF.Link | None
email_content: DF.TextEditor | None
email_header: DF.Data | None
for_user: DF.Link | None
from_user: DF.Link | None
link: DF.Data | None
link: DF.SmallText | None
read: DF.Check
subject: DF.Text | None
type: DF.Literal["", "Mention", "Assignment", "Share", "Alert"]