From 222f51b4d02edf5c84fad50c365e9f04de454e21 Mon Sep 17 00:00:00 2001 From: khushi8112 Date: Mon, 23 Feb 2026 01:39:17 +0530 Subject: [PATCH] feat: standard print format for Sales Order and Purchase Invoice (cherry picked from commit 371efce88a2b1df2d159e98547be02296590772d) --- .../purchase_invoice_standard/__init__.py | 0 .../purchase_invoice_standard.json | 33 +++++++++++++++++++ .../__init__.py | 0 .../purchase_invoice_with_item_image.json | 33 +++++++++++++++++++ .../purchase_order_with_item_image.json | 4 +-- erpnext/controllers/accounts_controller.py | 4 ++- erpnext/public/js/print.js | 13 +++++++- .../sales_order_standard/__init__.py | 0 .../sales_order_standard.json | 33 +++++++++++++++++++ .../sales_order_with_item_image/__init__.py | 0 .../sales_order_with_item_image.json | 33 +++++++++++++++++++ 11 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 erpnext/accounts/print_format/purchase_invoice_standard/__init__.py create mode 100644 erpnext/accounts/print_format/purchase_invoice_standard/purchase_invoice_standard.json create mode 100644 erpnext/accounts/print_format/purchase_invoice_with_item_image/__init__.py create mode 100644 erpnext/accounts/print_format/purchase_invoice_with_item_image/purchase_invoice_with_item_image.json create mode 100644 erpnext/selling/print_format/sales_order_standard/__init__.py create mode 100644 erpnext/selling/print_format/sales_order_standard/sales_order_standard.json create mode 100644 erpnext/selling/print_format/sales_order_with_item_image/__init__.py create mode 100644 erpnext/selling/print_format/sales_order_with_item_image/sales_order_with_item_image.json diff --git a/erpnext/accounts/print_format/purchase_invoice_standard/__init__.py b/erpnext/accounts/print_format/purchase_invoice_standard/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/purchase_invoice_standard/purchase_invoice_standard.json b/erpnext/accounts/print_format/purchase_invoice_standard/purchase_invoice_standard.json new file mode 100644 index 00000000000..4e4d3d0575f --- /dev/null +++ b/erpnext/accounts/print_format/purchase_invoice_standard/purchase_invoice_standard.json @@ -0,0 +1,33 @@ +{ + "absolute_value": 0, + "align_labels_right": 0, + "creation": "2026-02-20 18:45:58.615902", + "custom_format": 1, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Purchase Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font_size": 14, + "html": "{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\t{% if letter_head and not no_letterhead %}\n\t\t
{{ letter_head }}
\n\t{% endif %}\n\t{% if print_heading_template %}\n\t\t{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n\t{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t{{ _(\"Supplier Name\") }}: {{doc.supplier_name }}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Due Date\") }}: {{\n\t\t\t\t\tfrappe.utils.format_date(doc.due_date) }}\n\t\t\t\t
{{ _(\"Invoice Number\") }}: {{ doc.name }}\n\t\t\t\t\t{{ _(\"Invoice Date\") }}: {{\n\t\t\t\t\tfrappe.utils.format_date(doc.posting_date) }}\n\t\t\t\t
{{ _(\"Supplier Address\") }}:
\n\t\t\t\t\t{% if doc.supplier_address %}\n\t\t\t\t\t\t{% set supplier_address = frappe.db.get_value(\"Address\", doc.supplier_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.supplier_name }}
\n\t\t\t\t\t\t{{ supplier_address.address_line1 or \"\" }}
\n\t\t\t\t\t\t{% if supplier_address.address_line2 %}{{ supplier_address.address_line2 }}
{% endif %}\n\t\t\t\t\t\t{{ supplier_address.city or \"\" }} {{ supplier_address.state or \"\" }} {{ supplier_address.pincode or \"\" }} {{ supplier_address.country or \"\" }}
\n\t\t\t\t\t{% endif %}\n\t\t\t\t
{{ _(\"Company Address\") }}:
\n {% if doc.billing_address %}\n {% set billing_address = frappe.db.get_value(\"Address\", doc.billing_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.company }}
\n {{ billing_address.get(\"address_line1\") or \"\" }}
\n {% if billing_address.get(\"address_line2\") %}{{ billing_address.get(\"address_line2\") }}
{% endif %}\n {{ billing_address.get(\"city\") or \"\" }}, {{ billing_address.get(\"state\") or \"\" }} {{ billing_address.get(\"pincode\") or \"\" }}, {{ billing_address.get(\"country\") or \"\" }}
\n {% endif %}\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}{{ item.item_name }}{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}\n\t\t\t\t\t\t{{ item.get_formatted(\"net_amount\", doc) }}\n\t\t\t\t\t
\n\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t

{{ _(\"Total in words\") }}

\n\t\t\t\t
{{ doc.in_words }}
\n\t\t\t
\n\t\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t{%- endfor -%}\n\t\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
{{ _(\"Sub Total:\") }}
{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t\t
{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t\t
{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):
{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t\t
{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t\t
{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ _(\"Grand Total:\") }}{{ doc.get_formatted(\"grand_total\", doc) }}
\n\t\t\t
\n\n\t\t\n\t\t
\n\t\t\t{% if doc.terms %}\n\t\t\t
\n\t\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t\t{{ doc.terms}}\n\t\t\t
\n\t\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", + "idx": 0, + "line_breaks": 0, + "margin_bottom": 15.0, + "margin_left": 15.0, + "margin_right": 15.0, + "margin_top": 15.0, + "modified": "2026-02-23 00:46:57.038144", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Purchase Invoice Standard", + "owner": "Administrator", + "page_number": "Hide", + "pdf_generator": "wkhtmltopdf", + "print_format_builder": 0, + "print_format_builder_beta": 0, + "print_format_for": "DocType", + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +} diff --git a/erpnext/accounts/print_format/purchase_invoice_with_item_image/__init__.py b/erpnext/accounts/print_format/purchase_invoice_with_item_image/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/purchase_invoice_with_item_image/purchase_invoice_with_item_image.json b/erpnext/accounts/print_format/purchase_invoice_with_item_image/purchase_invoice_with_item_image.json new file mode 100644 index 00000000000..310a2f1b0cb --- /dev/null +++ b/erpnext/accounts/print_format/purchase_invoice_with_item_image/purchase_invoice_with_item_image.json @@ -0,0 +1,33 @@ +{ + "absolute_value": 0, + "align_labels_right": 0, + "creation": "2026-02-20 18:47:19.416106", + "custom_format": 1, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Purchase Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font_size": 14, + "html": "{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\n{% if letter_head and not no_letterhead %}\n
{{ letter_head }}
\n{% endif %}\n{% if print_heading_template %}\n{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Supplier Name:
\n\t\t\t\t\t\t
Supplier Address:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.supplier_name }}
\n\t\t\t\t\t\t
\n \t\t\t\t\t{% if doc.supplier_address %}\n \t\t\t\t\t\t{% set supplier_address = frappe.db.get_value(\"Address\", doc.supplier_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.supplier_name }}
\n \t\t\t\t\t\t{{ supplier_address.address_line1 or \"\" }}
\n \t\t\t\t\t\t{% if supplier_address.address_line2 %}{{ supplier_address.address_line2 }}
{% endif %}\n \t\t\t\t\t\t{{ supplier_address.city or \"\" }} {{ supplier_address.state or \"\" }} {{ supplier_address.pincode or \"\" }} {{ supplier_address.country or \"\" }}
\n \t\t\t\t\t{% endif %}\n\t\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Purchase Invoice:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.name }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Posting Date:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.posting_date) }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Due By:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.due_date) }}
\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% if item.image %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% endif %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{{ item.item_name }}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}{{ item.get_formatted(\"net_amount\", doc) }}
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t{%- endfor -%}\n\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t
{{ _(\"Sub Total:\") }}{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
\n\t\t
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t {{ _(\"In Words: \") }}{{ doc.in_words }}\n\t\t\t\t\t\t
\n\t\t\t\t\t
{{ _(\"Grand Total:\") }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{{ doc.get_formatted(\"grand_total\", doc) }}\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t
\n\n\n\t\t\n\t\t{% if doc.terms %}\n\t\t
\n\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t{{ doc.terms}}\n\t\t
\n\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", + "idx": 0, + "line_breaks": 0, + "margin_bottom": 15.0, + "margin_left": 15.0, + "margin_right": 15.0, + "margin_top": 15.0, + "modified": "2026-02-23 00:55:47.184575", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Purchase Invoice with Item Image", + "owner": "Administrator", + "page_number": "Hide", + "pdf_generator": "wkhtmltopdf", + "print_format_builder": 0, + "print_format_builder_beta": 0, + "print_format_for": "DocType", + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +} diff --git a/erpnext/buying/print_format/purchase_order_with_item_image/purchase_order_with_item_image.json b/erpnext/buying/print_format/purchase_order_with_item_image/purchase_order_with_item_image.json index 2f4c09b0cb6..df27dbbe479 100644 --- a/erpnext/buying/print_format/purchase_order_with_item_image/purchase_order_with_item_image.json +++ b/erpnext/buying/print_format/purchase_order_with_item_image/purchase_order_with_item_image.json @@ -9,14 +9,14 @@ "docstatus": 0, "doctype": "Print Format", "font_size": 14, - "html": "{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\n{% if letter_head and not no_letterhead %}\n
{{ letter_head }}
\n{% endif %}\n{% if print_heading_template %}\n{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Customer Name:
\n\t\t\t\t\t\t
Supplier Address:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.supplier_name }}
\n\t\t\t\t\t\t
\n \t\t\t\t\t{% if doc.supplier_address %}\n \t\t\t\t\t\t{% set supplier_address = frappe.db.get_value(\"Address\", doc.supplier_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.supplier_name }}
\n \t\t\t\t\t\t{{ supplier_address.address_line1 or \"\" }}
\n \t\t\t\t\t\t{% if supplier_address.address_line2 %}{{ supplier_address.address_line2 }}
{% endif %}\n \t\t\t\t\t\t{{ supplier_address.city or \"\" }} {{ supplier_address.state or \"\" }} {{ supplier_address.pincode or \"\" }} {{ supplier_address.country or \"\" }}
\n \t\t\t\t\t{% endif %}\n\t\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Purchase Order:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.name }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Order Date:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.transaction_date) }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Required By:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.schedule_date) }}
\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% if item.image %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% endif %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{{ item.item_name }}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}{{ item.get_formatted(\"net_amount\", doc) }}
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t{%- endfor -%}\n\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t
{{ _(\"Sub Total:\") }}{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
\n\t\t
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t {{ _(\"In Words: \") }}{{ doc.in_words }}\n\t\t\t\t\t\t
\n\t\t\t\t\t
{{ _(\"Grand Total:\") }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{{ doc.get_formatted(\"grand_total\", doc) }}\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t
\n\n\n\t\t\n\t\t{% if doc.terms %}\n\t\t
\n\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t{{ doc.terms}}\n\t\t
\n\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", + "html": "{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\n{% if letter_head and not no_letterhead %}\n
{{ letter_head }}
\n{% endif %}\n{% if print_heading_template %}\n{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Supplier Name:
\n\t\t\t\t\t\t
Supplier Address:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.supplier_name }}
\n\t\t\t\t\t\t
\n \t\t\t\t\t{% if doc.supplier_address %}\n \t\t\t\t\t\t{% set supplier_address = frappe.db.get_value(\"Address\", doc.supplier_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.supplier_name }}
\n \t\t\t\t\t\t{{ supplier_address.address_line1 or \"\" }}
\n \t\t\t\t\t\t{% if supplier_address.address_line2 %}{{ supplier_address.address_line2 }}
{% endif %}\n \t\t\t\t\t\t{{ supplier_address.city or \"\" }} {{ supplier_address.state or \"\" }} {{ supplier_address.pincode or \"\" }} {{ supplier_address.country or \"\" }}
\n \t\t\t\t\t{% endif %}\n\t\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Purchase Order:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.name }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Order Date:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.transaction_date) }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ _(\"Required By:\") }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.schedule_date) }}
\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% if item.image %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% endif %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{{ item.item_name }}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}{{ item.get_formatted(\"net_amount\", doc) }}
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t{%- endfor -%}\n\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t
{{ _(\"Sub Total:\") }}{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
\n\t\t
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t {{ _(\"In Words: \") }}{{ doc.in_words }}\n\t\t\t\t\t\t
\n\t\t\t\t\t
{{ _(\"Grand Total:\") }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{{ doc.get_formatted(\"grand_total\", doc) }}\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t
\n\n\n\t\t\n\t\t{% if doc.terms %}\n\t\t
\n\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t{{ doc.terms}}\n\t\t
\n\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", "idx": 0, "line_breaks": 0, "margin_bottom": 15.0, "margin_left": 15.0, "margin_right": 15.0, "margin_top": 15.0, - "modified": "2025-11-30 20:07:51.896474", + "modified": "2026-02-23 01:34:16.965402", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order with Item Image", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 9d81a6318c0..6a75859cdb0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -4296,7 +4296,7 @@ def get_missing_company_details(doctype, docname): from frappe.contacts.doctype.address.address import get_address_display_list company = frappe.db.get_value(doctype, docname, "company") - if doctype == "Purchase Order": + if doctype in ["Purchase Order", "Purchase Invoice"]: company_address = frappe.db.get_value(doctype, docname, "billing_address") else: company_address = frappe.db.get_value(doctype, docname, "company_address") @@ -4392,6 +4392,8 @@ def update_doc_company_address(current_doctype, docname, company_address, detail address_field_map = { "Purchase Order": ("billing_address", "billing_address_display"), + "Purchase Invoice": ("billing_address", "billing_address_display"), + "Sales Order": ("company_address", "company_address_display"), "Sales Invoice": ("company_address", "company_address_display"), "Delivery Note": ("company_address", "company_address_display"), "POS Invoice": ("company_address", "company_address_display"), diff --git a/erpnext/public/js/print.js b/erpnext/public/js/print.js index 105a580aed6..4f397ef2047 100644 --- a/erpnext/public/js/print.js +++ b/erpnext/public/js/print.js @@ -1,11 +1,22 @@ -const doctype_list = ["Sales Invoice", "Delivery Note", "Purchase Order", "POS Invoice"]; +const doctype_list = [ + "Sales Order", + "Sales Invoice", + "Delivery Note", + "Purchase Order", + "Purchase Invoice", + "POS Invoice", +]; const allowed_print_formats = [ + "Sales Order Standard", + "Sales Order with Item Image", "Sales Invoice Standard", "Sales Invoice with Item Image", "Delivery Note Standard", "Delivery Note with Item Image", "Purchase Order Standard", "Purchase Order with Item Image", + "Purchase Invoice Standard", + "Purchase Invoice with Item Image", "POS Invoice Standard", "POS Invoice with Item Image", ]; diff --git a/erpnext/selling/print_format/sales_order_standard/__init__.py b/erpnext/selling/print_format/sales_order_standard/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/selling/print_format/sales_order_standard/sales_order_standard.json b/erpnext/selling/print_format/sales_order_standard/sales_order_standard.json new file mode 100644 index 00000000000..13651985c2e --- /dev/null +++ b/erpnext/selling/print_format/sales_order_standard/sales_order_standard.json @@ -0,0 +1,33 @@ +{ + "absolute_value": 0, + "align_labels_right": 0, + "creation": "2026-02-23 01:03:48.196656", + "custom_format": 1, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Sales Order", + "docstatus": 0, + "doctype": "Print Format", + "font_size": 14, + "html": "\n\n{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\t{% if letter_head and not no_letterhead %}\n\t\t
{{ letter_head }}
\n\t{% endif %}\n\t{% if print_heading_template %}\n\t\t{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n\t{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t{{ _(\"Customer Name\") }}: {{doc.customer_name }}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Dilevery Date\") }}: {{\n\t\t\t\t\tfrappe.utils.format_date(doc.delivery_date) }}\n\t\t\t\t
{{ _(\"Sales Order\") }}: {{ doc.name }}\n\t\t\t\t\t{{ _(\"Posting Date\") }}: {{\n\t\t\t\t\tfrappe.utils.format_date(doc.transaction_date) }}\n\t\t\t\t
{{ _(\"Bill From\") }}:
\n\t\t\t\t\t{% if doc.company_address %}\n {% set company_address = frappe.db.get_value(\"Address\", doc.company_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.company }}
\n {{ company_address.get(\"address_line1\") or \"\" }}
\n {% if company_address.get(\"address_line2\") %}{{ company_address.get(\"address_line2\") }}
{% endif %}\n {{ company_address.get(\"city\") or \"\" }}, {{ company_address.get(\"state\") or \"\" }} {{ company_address.get(\"pincode\") or \"\" }}, {{ company_address.get(\"country\") or \"\" }}
\n {% endif %}\n\t\t\t\t
{{ _(\"Bill To\") }}:
\n\t\t\t\t {% if doc.customer_address %}\n\t\t\t\t\t\t{% set customer_address = frappe.db.get_value(\"Address\", doc.customer_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n {{ doc.customer_name }}
\n\t\t\t\t\t\t{{ customer_address.address_line1 or \"\" }}
\n\t\t\t\t\t\t{% if customer_address.address_line2 %}{{ customer_address.address_line2 }}
{% endif %}\n\t\t\t\t\t\t{{ customer_address.city or \"\" }} {{ customer_address.state or \"\" }} {{ customer_address.pincode or \"\" }} {{ customer_address.country or \"\" }}
\n\t\t\t\t\t{% endif %}\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}{{ item.item_name }}{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}\n\t\t\t\t\t\t{{ item.get_formatted(\"net_amount\", doc) }}\n\t\t\t\t\t
\n\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t

{{ _(\"Total in words\") }}

\n\t\t\t\t
{{ doc.in_words }}
\n\t\t\t
\n\t\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t{%- endfor -%}\n\t\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
{{ _(\"Sub Total:\") }}
{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t\t
{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t\t
{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):
{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t\t
{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t\t
{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ _(\"Grand Total:\") }}{{ doc.get_formatted(\"grand_total\", doc) }}
\n\t\t\t
\n\n\t\t\n\t\t
\n\t\t\t{% if doc.terms %}\n\t\t\t
\n\t\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t\t{{ doc.terms}}\n\t\t\t
\n\t\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", + "idx": 0, + "line_breaks": 0, + "margin_bottom": 15.0, + "margin_left": 15.0, + "margin_right": 15.0, + "margin_top": 15.0, + "modified": "2026-02-23 01:06:39.568460", + "modified_by": "Administrator", + "module": "Selling", + "name": "Sales Order Standard", + "owner": "Administrator", + "page_number": "Hide", + "pdf_generator": "wkhtmltopdf", + "print_format_builder": 0, + "print_format_builder_beta": 0, + "print_format_for": "DocType", + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +} diff --git a/erpnext/selling/print_format/sales_order_with_item_image/__init__.py b/erpnext/selling/print_format/sales_order_with_item_image/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/selling/print_format/sales_order_with_item_image/sales_order_with_item_image.json b/erpnext/selling/print_format/sales_order_with_item_image/sales_order_with_item_image.json new file mode 100644 index 00000000000..d27fa63154d --- /dev/null +++ b/erpnext/selling/print_format/sales_order_with_item_image/sales_order_with_item_image.json @@ -0,0 +1,33 @@ +{ + "absolute_value": 0, + "align_labels_right": 0, + "creation": "2026-02-23 01:08:54.564508", + "custom_format": 1, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Sales Order", + "docstatus": 0, + "doctype": "Print Format", + "font_size": 14, + "html": "{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}\n\n{% if letter_head and not no_letterhead %}\n
{{ letter_head }}
\n{% endif %}\n{% if print_heading_template %}\n{{ frappe.render_template(print_heading_template, {\"doc\":doc}) }}\n{% endif %}\n{%- endmacro -%}\n\n{% for page in layout %}\n
\n\t
\n\t\t{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}\n\t
\n\t{%- if doc.meta.is_submittable and doc.docstatus==2-%}\n\t\t
\n\t\t\t

{{ _(\"CANCELLED\") }}

\n\t\t
\n\t{%- endif -%}\n\t{%- if doc.meta.is_submittable and doc.docstatus==0 and (print_settings==None or print_settings.add_draft_heading) -%}\n\t\t
\n\t\t\t

{{ _(\"DRAFT\") }}

\n\t\t
\n\t{%- endif -%}\n\n\t\n\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\n\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Customer Name:
\n\t\t\t\t\t\t
Bill to:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.customer_name }}
\n\t\t\t\t\t\t
\n \t\t\t\t\t{% if doc.customer_address %}\n \t\t\t\t\t\t{% set customer_address = frappe.db.get_value(\"Address\", doc.customer_address, [\"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\"], as_dict=True) %}\n \t\t\t\t\t\t{{ customer_address.address_line1 or \"\" }}
\n \t\t\t\t\t\t{% if customer_address.address_line2 %}{{ customer_address.address_line2 }}
{% endif %}\n \t\t\t\t\t\t{{ customer_address.city or \"\" }} {{ customer_address.state or \"\" }} {{ customer_address.pincode or \"\" }} {{ customer_address.country or \"\" }}
\n \t\t\t\t\t{% endif %}\n\t\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Sales Order:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ doc.name }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Order Date:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.transaction_date) }}
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
Delivery Date:
\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t
{{ frappe.utils.format_date(doc.delivery_date) }}
\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\n\t\t{% set item_naming_by = frappe.db.get_single_value(\"Stock Settings\", \"item_naming_by\") %}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{% for item in doc.items %}\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{% if item_naming_by != \"Item Code\" %}\n\t\t\t\t\t\t\n\t\t\t\t\t{% endif %}\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{% endfor %}\n\t\t\t\n\t\t
{{ _(\"No\") }}{{ _(\"Item\") }}{{ _(\"Item Code\") }}{{ _(\"Quantity\") }}{{ _(\"Rate\") }}{{ _(\"Amount\") }}
{{ loop.index }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% if item.image %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{% endif %}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{{ item.item_name }}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
{{ item.item_code }}{{ item.get_formatted(\"qty\", 0) }} {{ item.uom }}{{ item.get_formatted(\"net_rate\", doc) }}{{ item.get_formatted(\"net_amount\", doc) }}
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t{%- if doc.apply_discount_on == \"Net Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- for tax in doc.taxes -%}\n\t\t\t\t\t{%- if (tax.tax_amount or print_settings.print_taxes_with_zero_amount) and (not tax.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t{%- endif -%}\n\t\t\t\t{%- endfor -%}\n\t\t\t\t{%- if doc.apply_discount_on == \"Grand Total\" -%}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{%- endif -%}\n\t\t\t
{{ _(\"Sub Total:\") }}{{ doc.get_formatted(\"total\", doc) }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
{{ tax.get_formatted(\"description\") }} ({{ tax.get_formatted(\"rate\") }}%):{{ tax.get_formatted(\"tax_amount\") }}
\n\t\t\t\t\t\t\t{{ _(\"Discount\") }} ({{ doc.additional_discount_percentage }}%):\n\t\t\t\t\t\t{{ doc.get_formatted(\"discount_amount\", doc) }}
\n\t\t
\n\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t {{ _(\"In Words: \") }}{{ doc.in_words }}\n\t\t\t\t\t\t
\n\t\t\t\t\t
{{ _(\"Grand Total:\") }}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{{ doc.get_formatted(\"grand_total\", doc) }}\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t
\n\n\n\t\t\n\t\t{% if doc.terms %}\n\t\t
\n\t\t\t
{{ _(\"Terms and Conditions\") }}
\n\t\t\t{{ doc.terms}}\n\t\t
\n\t\t{% endif %}\n\t
\n
\n{% endfor %}\n", + "idx": 0, + "line_breaks": 0, + "margin_bottom": 15.0, + "margin_left": 15.0, + "margin_right": 15.0, + "margin_top": 15.0, + "modified": "2026-02-23 01:08:54.564508", + "modified_by": "Administrator", + "module": "Selling", + "name": "Sales Order with Item Image", + "owner": "Administrator", + "page_number": "Hide", + "pdf_generator": "wkhtmltopdf", + "print_format_builder": 0, + "print_format_builder_beta": 0, + "print_format_for": "DocType", + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +}