diff --git a/frappe/printing/doctype/letter_head/letter_head.json b/frappe/printing/doctype/letter_head/letter_head.json index 119a59120f..f4aa731b86 100644 --- a/frappe/printing/doctype/letter_head/letter_head.json +++ b/frappe/printing/doctype/letter_head/letter_head.json @@ -7,29 +7,32 @@ "document_type": "Setup", "engine": "InnoDB", "field_order": [ - "letter_head_for", "letter_head_name", "module", "source", "footer_source", "column_break_3", + "letter_head_for", "standard", "disabled", "is_default", "letter_head_image_section", + "align", "image", + "column_break_dpzk", "image_height", "image_width", - "align", - "header_section", - "content", - "footer_section", - "footer", "footer_image_section", + "footer_align", "footer_image", + "column_break_kfvf", "footer_image_height", "footer_image_width", - "footer_align", + "header_section", + "content", + "custom_css", + "footer_section", + "footer", "scripts_section", "header_script", "footer_script", @@ -47,7 +50,6 @@ "unique": 1 }, { - "depends_on": "letter_head_name", "fieldname": "source", "fieldtype": "Select", "label": "Letter Head Based On", @@ -59,7 +61,6 @@ }, { "default": "0", - "depends_on": "letter_head_name", "fieldname": "disabled", "fieldtype": "Check", "in_list_view": 1, @@ -69,7 +70,6 @@ }, { "default": "0", - "depends_on": "letter_head_name", "fieldname": "is_default", "fieldtype": "Check", "in_list_view": 1, @@ -79,45 +79,42 @@ "search_index": 1 }, { - "depends_on": "eval:doc.letter_head_name && doc.source === 'Image'", + "depends_on": "eval:doc.source === 'Image'", "fieldname": "letter_head_image_section", "fieldtype": "Section Break", "label": "Letter Head Image" }, { - "depends_on": "eval:doc.letter_head_name && doc.source === 'Image'", "fieldname": "image", "fieldtype": "Attach Image", "label": "Image" }, { - "depends_on": "eval:doc.source==='HTML' && doc.letter_head_name", + "depends_on": "eval:doc.source==='HTML'", "fieldname": "header_section", "fieldtype": "Section Break", "label": "Header" }, { - "depends_on": "eval:!doc.__islocal && doc.source==='HTML'", + "depends_on": "eval:doc.source==='HTML'", "description": "Letter Head in HTML", "fieldname": "content", "fieldtype": "HTML Editor", - "ignore_xss_filter": 1, "label": "Header HTML", "oldfieldname": "content", "oldfieldtype": "Text Editor" }, { - "depends_on": "eval:doc.footer_source==='HTML' && doc.letter_head_name", + "depends_on": "eval:doc.footer_source==='HTML'", "fieldname": "footer_section", "fieldtype": "Section Break", "label": "Footer" }, { - "depends_on": "eval:!doc.__islocal", + "depends_on": "eval:doc.footer_source==='HTML'", "description": "Footer will display correctly only in PDF", "fieldname": "footer", "fieldtype": "HTML Editor", - "ignore_xss_filter": 1, "label": "Footer HTML" }, { @@ -138,7 +135,7 @@ "label": "Image Width (px)" }, { - "depends_on": "eval:doc.footer_source==='Image' && doc.letter_head_name", + "depends_on": "eval:doc.footer_source==='Image'", "fieldname": "footer_image_section", "fieldtype": "Section Break", "label": "Footer Image" @@ -165,22 +162,20 @@ "options": "Left\nRight\nCenter" }, { - "default": "HTML", - "depends_on": "letter_head_name", "fieldname": "footer_source", "fieldtype": "Select", "label": "Footer Based On", "options": "Image\nHTML" }, { - "depends_on": "eval:!doc.__islocal && doc.source==='HTML'", + "depends_on": "eval:doc.source==='HTML'", "fieldname": "header_script", "fieldtype": "Code", "label": "Header Script", "options": "Javascript" }, { - "depends_on": "eval:!doc.__islocal && doc.footer_source==='HTML'", + "depends_on": "eval:doc.footer_source==='HTML'", "fieldname": "footer_script", "fieldtype": "Code", "label": "Footer Script", @@ -188,8 +183,8 @@ }, { "collapsible": 1, - "collapsible_depends_on": "eval: doc.header_script || doc.footer_script", - "depends_on": "eval: !doc.__islocal", + "collapsible_depends_on": "eval:doc.header_script || doc.footer_script", + "depends_on": "eval:doc.source === 'HTML' || doc.footer_source === 'HTML'", "fieldname": "scripts_section", "fieldtype": "Section Break", "label": "Scripts" @@ -223,6 +218,21 @@ "label": "Module", "mandatory_depends_on": "eval: doc.standard == \"Yes\"", "options": "Module Def" + }, + { + "fieldname": "column_break_dpzk", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_kfvf", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval:doc.source === 'HTML'", + "fieldname": "custom_css", + "fieldtype": "Code", + "label": "Custom CSS", + "options": "CSS" } ], "icon": "fa fa-font", @@ -230,7 +240,7 @@ "links": [], "make_attachments_public": 1, "max_attachments": 3, - "modified": "2026-04-08 13:15:24.935222", + "modified": "2026-04-24 13:17:34.972069", "modified_by": "Administrator", "module": "Printing", "name": "Letter Head", diff --git a/frappe/printing/doctype/letter_head/letter_head.py b/frappe/printing/doctype/letter_head/letter_head.py index 220a09cac1..2582b40674 100644 --- a/frappe/printing/doctype/letter_head/letter_head.py +++ b/frappe/printing/doctype/letter_head/letter_head.py @@ -19,6 +19,7 @@ class LetterHead(Document): align: DF.Literal["Left", "Right", "Center"] content: DF.HTMLEditor | None + custom_css: DF.Code | None disabled: DF.Check footer: DF.HTMLEditor | None footer_align: DF.Literal["Left", "Right", "Center"] @@ -39,11 +40,6 @@ class LetterHead(Document): standard: DF.Literal["No", "Yes"] # end: auto-generated types - def before_insert(self): - # for better UX, let user set from attachment - if not frappe.flags.in_migrate and not frappe.flags.in_install: - self.source = "Image" - def on_trash(self): from frappe.defaults import clear_default diff --git a/frappe/utils/print_format.py b/frappe/utils/print_format.py index 3a3770bce1..62440c3358 100644 --- a/frappe/utils/print_format.py +++ b/frappe/utils/print_format.py @@ -294,7 +294,7 @@ def render_letterhead_for_print(letterhead: str | None = None, doc: dict | str | frappe.db.get_value( "Letter Head", letterhead or {"is_default": 1}, - ["content", "footer", "header_script", "footer_script"], + ["content", "footer", "header_script", "footer_script", "custom_css"], as_dict=True, ) or {} @@ -305,9 +305,11 @@ def render_letterhead_for_print(letterhead: str | None = None, doc: dict | str | if letter_head.content: header = render_template(letter_head.content, {"doc": context_doc}) + if letter_head.custom_css: + header += f"\n\n" + rendered["header"] = header if letter_head.header_script: header += f"\n\n" - rendered["header"] = header if letter_head.footer: footer = render_template(letter_head.footer, {"doc": context_doc}) diff --git a/frappe/www/printview.py b/frappe/www/printview.py index ff2b048305..15e9ea1854 100644 --- a/frappe/www/printview.py +++ b/frappe/www/printview.py @@ -230,6 +230,12 @@ def get_rendered_template( if letter_head.content: letter_head.content = frappe.utils.jinja.render_template(letter_head.content, {"doc": doc.as_dict()}) + if letter_head.custom_css: + letter_head.content += f""" + + """ if letter_head.header_script: letter_head.content += f"""