How to customize Quotation print format

Hello,

I need to customize quotation print format. By loading print format list page I could not find the template for Quotation so I think this cannot be modified.

Is there a way to copy that template as the starting point? I only need to modify a few elements.

Regards
Jaime

As far as I know, you can’t modify the Standard Template via Print Format. But you can create a new Print Format for that document and modify what you want.
When you’ll print the document, you need to select the print format you have created (or set it as default)

I tried doing that way few several months, but every time I wanted to make changes it was a struggle. Your best option is to create a jinja2 format (and maybe set that as the default).
My sample (for an invoice - but should be the same principles for any doc) with its output is shown here

2 Likes

@mel_erp I know that, but you tell “modify what you want”. That’s the point. I want not to start all over again but with the current template.

When you do a Print Format based on Quotation, it already loads the template. So you just have to add what you want.

1 Like

That’s not true.

Let me tell you the steps because perhaps you don’t understand what I need to accomplish:

  1. Load Print Format list page

  2. Search DocType: Quotation. Nothing is shown.

  3. Click “New” button

  4. Set “Name” field as “Cotización”

  5. Set checkbox “Custom Format”.

  6. HTML text area appears empty

On the last step, I need the HTML field to be loaded with the current template. From that point, I can change what I need to change.

Regards
Jaime

Step 1: Create a new print format and save


Step 2: Edit Format

Step 3: Add/Drag and drop whatever you need from the left of the page (I guess you need the ‘Custom HTML’) and write the html/Jinja you need.
Step 4: Choose the print format when you print

That’s how you customise Quotation Print format.

I think someting is still missing.

Your steps are for creating the HTML from scratch… I know how to do it, however, I need the current quotation format as the starting point in HTML format.

It is obvious I can just add several HTML tags or Jinja instructions in order to create the format, but I need to get the current quotation format in order to just modified.

Currently, if I have a quotation and then print it, ERPNext shows me the quotation. I need that HTML/Jinja instructions so that I can only modify a few elements, for example, typography.

Furthermore, without choosing custom HTML format I am able to edit the format using this page:

That is not what I am looking for… for example, no Bootstrap CSS is taken into account when modifying the header. On the other hand, I want just to add the company logo in the header… with that page, I don’t have a way to add it.

I hope this is finally clear now.

Regards

Jaime

Finally I have created the HTML from scratch.

Regards
Jaime

Jaime, would you be willing to share your code?

I am having particular issues inserting page breaks in html custom print formats.

Here’s the final full code. At the end of the format I am displaying other new added variables to the document, doc.detail and doc.solution.

Page break is added using <div class="page-break"></div>

<table class="table" style="margin-top: 0; border-bottom: solid 1px #d1d8dd">
    <tbody>
        <tr>
            <td style="width: 10%; border: 0"><img src="{{ frappe.db.get_value("Company", doc.company, "company_logo") or "" }}" alt="" style="height: 80px !important" /></td>
            <td style="width: 70%; border: 0">
                <table class="table" style="margin: 0">
                    <thead>
                        <tr>
                            <td class="text-center" style="border: 0; padding: 0 !important"><h3 style="margin: 0">Development, Systems & Technologies</h3></td>
                        </tr>
                        <tr>
                            <td class="text-center" style="border: 0; padding: 0 !important"><small>Proyectos de Ingeniería Electrónica e Informática</small></td>
                        </tr>
                        <tr>
                            <td class="text-center" style="border: 0; padding: 0 !important"><small>Sistemas de Control Biométrico y RFID: Acceso - Asistencia - Comedores - Visitas</small></td>
                        </tr>
                        <tr>
                            <td class="text-center" style="border: 0; padding: 0 !important"><small>Desarrollo de Software: Windows - Linux - Web - Móvil</small></td>
                        </tr>
                        <tr>
                            <td class="text-center" style="border: 0; padding: 0 !important"><small><a href="Web Page" target="_blank" class="text-info"><strong>Web Page</strong></a></small></td>
                        </tr>
                    </thead>
                </table>
            </td>
            <td style="width: 20%; border: 0">
                <table class="table table-bordered" style="margin: 0">
                    <tbody>
	                <tr>
                            <th class="text-center">{{ doc.select_print_heading or "Cotización" }}</th>
                        </tr>
	                <tr>
                            <td class="text-center">{{ doc.name | replace('QUO','') }}</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>

<div class="row">
    <div class="col-md-12">
        <div>
        <small>De nuestra consideración:</small>
        </div>
        <div style="text-indent: 40px; margin-top: 10px; text-align: justify">
            <small>Atendiendo a su amable solicitud, es para nosotros un agrado enviarle la cotización de los productos requeridos según el siguiente detalle:</small>
        </div>
    </div>
</div>

<table class="table table-bordered" style="margin-bottom: 0">
    <tbody>
        <tr>
	    <th class="text-center" width="15%"><small>RUT</small></th>
	    <th class="text-center" width="30%"><small>CLIENTE</small></th>
	    <th class="text-center" width="25%"><small>CONTACTO</small></th>
	    <th class="text-center" width="15%"><small>FECHA</small></th>
	    <th class="text-center" width="15%"><small>VALIDEZ</small></th>
        </tr>
        <tr>
            <td class="text-center">
                <small>
                    {% if false and doc.quotation_to=="Customer" %}
                        {{ frappe.db.get_value("Customer", doc.customer, "tax_id") or "" }}
                    {% endif %}
                </small>
            </td>
            <td class="text-center"><small>{{ doc.customer_name }}</small></td>
{% if doc.contact_display %}
            <td class="text-center"><small>{{ doc.contact_display }}</small></td> 
{% else %}
            <td class="text-center"><small>{{ frappe.db.get_value("Contact", doc.contact_person, "first_name") or "" }} {{ frappe.db.get_value("Contact", doc.contact_person, "last_name") or "" }}</small></td>
{% endif %}
            <td class="text-center"><small>{{ doc.get_formatted("transaction_date") }}</small></td>
            <td class="text-center"><small>{{ doc.get_formatted("valid_till") }}</small></td>
        </tr>
        <tr>
	    <th class="text-center"><small>TELÉFONO</small></th>
	    <th class="text-center"><small>CIUDAD</small></th>
	    <th class="text-center"><small>E-MAIL</small></th>
	    <th class="text-center"><small>DESCUENTO</small></th>
	    <th class="text-center"><small>T. PAGO</small></th>
        </tr>
        <tr>
            <td class="text-center"><small>{{ frappe.db.get_value("Contact", doc.contact_person, "phone") or "" }}</small></td>
{% if doc.customer_address %}
            <td class="text-center"><small>{{ frappe.db.get_value("Address", doc.customer_address, "city") or "" }}, {{ frappe.db.get_value("Address", doc.customer_address, "country") or "" }}</small></td>
{% else %}
            <td class="text-center"><small>&nbsp;</small></td>
{% endif %}
            <td class="text-center"><small>{{ doc.contact_email }}</small></td>
            <td class="text-center"><small>{{ doc.get_formatted("additional_discount_percentage") }} %</small></td>
            <td class="text-center"><small>{{ frappe.db.get_value("Payment Terms Template", doc.payment_terms_template, "template_name") or "CONTADO" }}</small></td>
        </tr>
    </tbody>
</table>

<table class="table table-bordered">
	<tbody>
                <tr>
                    <td colspan="6" class="text-left"><strong><small>Moneda: {{ frappe.db.get_value("Currency", doc.currency, "description") or frappe.db.get_value("Currency", doc.currency, "currency_name") }}</small></strong></td>
                </tr>                
		<tr>
			<th class="text-center"><small>ÍTEM</small></th>
                        <th class="text-center"><small>CÓDIGO</small></th>
			<th class="text-center"><small>DESCRIPCIÓN</small></th>
			<th class="text-center"><small>CANTIDAD</mall></th>
			<th class="text-center"><small>UNITARIO</small></th>
			<th class="text-center"><small>TOTAL</small></th>
		</tr>
		{%- for row in doc.items -%}
		<tr>
			<td style="width: 3%;"><small>{{ row.idx }}</small></td>
                        <td style="width: 6%;"><small>{{ row.item_code}}</small></td>
			<td style="width: 48%;">
                            <small>
                                <div class="col-12">{{ row.item_name }}</div>
                                {% if row.description|striptags != '-' %}
                                <div class="col-12">{{ row.description }}</div>
                                {% endif %}
                            </small>
                        </td>
			<td style="width: 13%; text-align: right;"><small>{{ row.qty }} {{ row.uom or row.stock_uom }}</small></td>
			<td style="width: 15%; text-align: right;"><small>{{ row.get_formatted("rate", doc) }}</small></td>
			<td style="width: 15%; text-align: right;"><small>{{
				row.get_formatted("amount", doc) }}</small></td>
		</tr>
		{%- endfor -%}
                {% if doc.discount_amount > 0 %}
                <tr>
                    <td colspan="5" class="text-right"><strong>SUB-TOTAL</strong></td>
                    <td class="text-right"><small>{{ doc.get_formatted("total") }}</small></td>
                </tr>
                <tr>
                    <td colspan="5" class="text-right"><strong>DESCUENTO</strong></td>
                    <td class="text-right"><small>{{ doc.get_formatted("discount_amount") }}</small></td>
                </tr>
                {% endif %}
                <tr>
                    <td colspan="5" class="text-right"><strong>TOTAL NETO</strong></td>
                    <td class="text-right"><small>{{ doc.get_formatted("net_total") }}</small></td>
                </tr>
                {%- for row in doc.taxes -%}
                <tr>
                    <td colspan="5" class="text-right"><strong>{{ row.description }} {{ row.rate }}%</strong></td>
                    <td class="text-right"><small>{{ row.get_formatted("tax_amount", doc) }}</small></td>
                </tr>
                {%- endfor -%}
                <tr>
                    <td colspan="5" class="text-right"><strong>TOTAL</strong></td>
                    {% if doc.rounded_total == 0 %}
                    <td class="text-right"><strong><small>{{ doc.get_formatted("grand_total") }}</small></strong>
                    {% else %}
                    <td class="text-right"><strong><small>{{ doc.get_formatted("rounded_total") }}</small></strong></td>
                    {% endif %}
                </tr>
                {% if false and frappe.db.get_value("Currency", doc.currency, "currency_name") != "CLF" %}
                <tr>
                    <td colspan="6" class="text-right"><strong><small>Son: {{ doc.in_words }}</small></strong></td>
                </tr>
                {% endif %}
	</tbody>
</table>

{% if doc.terms %}
<div class="page-break"></div>
<div class="panel panel-default">
    <div class="panel-heading"><strong><small>Términos y Condiciones</small></strong></div>
    <div class="panel-body"><small>{{ doc.terms }}</small></div>
</div>
{% endif %}

<div class="row">
    <div class="col-md-12">
            <small>Esperando una buena acogida y poniendo desde ya nuestra compañía a su servicio, se depide atentamente,</small>
    </div>
</div>
<div class="row">
    <table class="table" style="margin-top: 0;">
        <tbody>
            <tr>
                <td style="width: 70%; border: 0"></td>
                <td style="width: 30%; border: 0"><small>Name<br />Phone</small></td>
            </tr>
        </tbody>
    </table>
</div>

{% if doc.detail %}
<div class="page-break"></div>
<div class="row text-center"><h1><strong>Requerimientos</strong></h1></div>
<div class="row" style="margin-top: 20px">
    <div class="col-md-12">{{ doc.detail }}</div>
</div>
{% if doc.solution %}
<div class="row text-center"><h1><strong>Solución Propuesta</strong></h1></div>
<div class="row" style="margin-top: 20px">
    <div class="col-md-12">{{ doc.solution }}</div>
</div>
{% endif %}
{% endif %}

This is a custom CSS:

ul {
  margin-bottom: 0
}

.panel-heading {
  padding: 3px 15px !important;
}

.panel-body {
  padding: 5px 15px !important;
}

.print-format td, .print-format th {
    padding-top: 3px !important;
    padding-bottom: 3px !important;
}

Hope this helps,

Jaime

2 Likes

Hi,
for learning purpose could you attach print output and how to implement the same with details.

Thanks

Thanks! Will try it out.

Recently, I implemented a solution where Jinja in HTML field only calls a python script. The script itself generates the entire HTML on its own, all page breaks and such are handled internally with python. I found it a consistent accomplishment. Just having to hash out a table problem and then I will post the code.

1 Like

ref,