diff --git a/frappe/printing/doctype/print_format/print_format.js b/frappe/printing/doctype/print_format/print_format.js index cb9bd28570..f2dea7ff24 100644 --- a/frappe/printing/doctype/print_format/print_format.js +++ b/frappe/printing/doctype/print_format/print_format.js @@ -23,7 +23,7 @@ frappe.ui.form.on("Print Format", { }, render_buttons: function (frm) { frm.page.clear_inner_toolbar(); - if (!frm.is_new()) { + if (!frm.is_new() && frm.doc.print_format_for === "Doctype") { if (!frm.doc.custom_format) { frm.add_custom_button(__("Edit Format"), function () { if (!frm.doc.doc_type) { @@ -71,6 +71,11 @@ frappe.ui.form.on("Print Format", { doc_type: function (frm) { frm.trigger("hide_absolute_value_field"); }, + print_format_for: function (frm) { + if (frm.doc.print_format_for === "Report") { + frm.set_value("print_format_type", "JS"); + } + }, hide_absolute_value_field: function (frm) { // TODO: make it work with frm.doc.doc_type // Problem: frm isn't updated in some random cases diff --git a/frappe/printing/doctype/print_format/print_format.json b/frappe/printing/doctype/print_format/print_format.json index b8654a0816..8f9055928c 100644 --- a/frappe/printing/doctype/print_format/print_format.json +++ b/frappe/printing/doctype/print_format/print_format.json @@ -6,7 +6,9 @@ "doctype": "DocType", "engine": "InnoDB", "field_order": [ + "print_format_for", "doc_type", + "report", "module", "default_print_language", "column_break_3", @@ -43,14 +45,15 @@ ], "fields": [ { + "depends_on": "eval:doc.print_format_for == \"Doctype\"", "fieldname": "doc_type", "fieldtype": "Link", "in_filter": 1, "in_list_view": 1, "in_standard_filter": 1, "label": "DocType", - "options": "DocType", - "reqd": 1 + "mandatory_depends_on": "eval:doc.print_format_for == \"Doctype\"", + "options": "DocType" }, { "fieldname": "module", @@ -88,7 +91,7 @@ "label": "Custom Format" }, { - "depends_on": "custom_format", + "depends_on": "eval:doc.custom_format || doc.print_format_for == \"Report\"", "fieldname": "section_break_6", "fieldtype": "Section Break" }, @@ -98,16 +101,18 @@ "fieldname": "print_format_type", "fieldtype": "Select", "label": "Print Format Type", - "options": "Jinja\nJS" + "options": "Jinja\nJS", + "read_only_depends_on": "eval:doc.print_format_for == \"Report\"" }, { "default": "0", + "depends_on": "custom_format", "fieldname": "raw_printing", "fieldtype": "Check", "label": "Raw Printing" }, { - "depends_on": "eval:!doc.raw_printing", + "depends_on": "eval:(!doc.raw_printing) || (doc.print_format_for == \"Report\")", "fieldname": "html", "fieldtype": "Code", "label": "HTML", @@ -263,12 +268,31 @@ "fieldtype": "Select", "label": "PDF Generator", "options": "wkhtmltopdf" + }, + { + "default": "Doctype", + "fieldname": "print_format_for", + "fieldtype": "Select", + "label": "Print Format For", + "options": "Doctype\nReport" + }, + { + "depends_on": "eval:doc.print_format_for == \"Report\"", + "fieldname": "report", + "fieldtype": "Link", + "in_filter": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Report", + "mandatory_depends_on": "eval:doc.print_format_for == \"Report\"", + "options": "Report", + "reqd": 1 } ], "icon": "fa fa-print", "idx": 1, "links": [], - "modified": "2025-02-14 14:49:39.181074", + "modified": "2025-07-01 16:25:00.431623", "modified_by": "Administrator", "module": "Printing", "name": "Print Format", @@ -291,8 +315,9 @@ "select": 1 } ], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py index 7c96225013..ff041c23eb 100644 --- a/frappe/printing/doctype/print_format/print_format.py +++ b/frappe/printing/doctype/print_format/print_format.py @@ -26,7 +26,7 @@ class PrintFormat(Document): custom_format: DF.Check default_print_language: DF.Link | None disabled: DF.Check - doc_type: DF.Link + doc_type: DF.Link | None font: DF.Data | None font_size: DF.Int format_data: DF.Code | None @@ -43,9 +43,11 @@ class PrintFormat(Document): pdf_generator: DF.Literal["wkhtmltopdf"] print_format_builder: DF.Check print_format_builder_beta: DF.Check + print_format_for: DF.Literal["Doctype", "Report"] print_format_type: DF.Literal["Jinja", "JS"] raw_commands: DF.Code | None raw_printing: DF.Check + report: DF.Link show_section_headings: DF.Check standard: DF.Literal["No", "Yes"] # end: auto-generated types diff --git a/frappe/public/js/frappe/form/print_utils.js b/frappe/public/js/frappe/form/print_utils.js index 4b5bc3257c..03cf82902f 100644 --- a/frappe/public/js/frappe/form/print_utils.js +++ b/frappe/public/js/frappe/form/print_utils.js @@ -9,6 +9,29 @@ frappe.ui.get_print_settings = function (pdf, callback, letter_head, pick_column } var columns = [ + { + fieldtype: "Select", + fieldname: "orientation", + label: __("Orientation"), + options: [ + { value: "Landscape", label: __("Landscape") }, + { value: "Portrait", label: __("Portrait") }, + ], + default: "Landscape", + }, + { + fieldtype: "Link", + fieldname: "report", + label: __("Report"), + options: "Print Format", + default: letter_head || default_letter_head, + get_query: () => ({ + filters: { + print_format_for: "Report", + disabled: 0, + }, + }), + }, { fieldtype: "Check", fieldname: "with_letter_head", @@ -22,16 +45,6 @@ frappe.ui.get_print_settings = function (pdf, callback, letter_head, pick_column options: "Letter Head", default: letter_head || default_letter_head, }, - { - fieldtype: "Select", - fieldname: "orientation", - label: __("Orientation"), - options: [ - { value: "Landscape", label: __("Landscape") }, - { value: "Portrait", label: __("Portrait") }, - ], - default: "Landscape", - }, ]; if (pick_columns) { diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 26540d6d1f..cc14cae7b9 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -1481,11 +1481,15 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { }); } - print_report(print_settings) { - const custom_format = this.report_settings.html_format || null; + async print_report(print_settings) { + let custom_format = this.report_settings.html_format || null; const filters_html = this.get_filters_html_for_print(); const landscape = print_settings.orientation == "Landscape"; + if (print_settings.report) { + custom_format = await this.get_report_print_format(print_settings.report); + } + this.make_access_log("Print", "PDF"); frappe.render_grid({ template: print_settings.columns ? "print_grid" : custom_format, @@ -1502,16 +1506,20 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { }); } - pdf_report(print_settings) { + async pdf_report(print_settings) { const base_url = frappe.urllib.get_base_url(); const print_css = frappe.boot.print_css; const landscape = print_settings.orientation == "Landscape"; - const custom_format = this.report_settings.html_format || null; + let custom_format = this.report_settings.html_format || null; const columns = this.get_columns_for_print(print_settings, custom_format); const data = this.get_data_for_print(); const applied_filters = this.get_filter_values(); + if (print_settings.report) { + custom_format = await this.get_report_print_format(print_settings.report); + } + const filters_html = this.get_filters_html_for_print(); const template = print_settings.columns || !custom_format ? "print_grid" : custom_format; const content = frappe.render_template(template, { @@ -1554,6 +1562,22 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { frappe.render_pdf(html, print_settings); } + async get_report_print_format(report_name) { + const filters = { + name: report_name, + disabled: 0, + }; + const r = await frappe.db.get_value("Print Format", filters, ["html", "css"]); + if (r && r.message && r.message.html) { + const css = r.message.css || ""; + const html = r.message.html || ""; + return `${html}`; + } else { + frappe.msgprint(__("Print Format not found")); + return null; + } + } + get_filters_html_for_print() { const applied_filters = this.get_filter_values(); return Object.keys(applied_filters)