Odoo Sale Order and Quotation Tutorials

Add a menu item to Sales section

This menu below will appear under Sales > Orders

<record id="act_export_sale" model="ir.actions.act_window">
    <field name="name">Export Sales</field>
    <field name="res_model">wizard.sale.export.sale</field>
    <field name="view_mode">form</field>
    <field name="view_id" ref="export_sale_form_view"/>
    <field name="target">new</field>
</record>

<menuitem id="menu_sale_export" parent="sale.sale_order_menu" name="Export Sales" sequence="0" action="act_export_sale"/>

You need to write export_sale_form_view based on your need.

Inherit and Override Sale Report Document

Create a view file called custom_report_sale.xml then add it to manifest. You can add custom field or modify existing values in this view.

<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="custom_report_sale" inherit_id="sale.report_saleorder_document">
<xpath expr="//div[@class='page']" position="replace">
<div class="page">
<div class="oe_structure"/>
<h2>
<t t-if="not (env.context.get('proforma', False) or is_pro_forma)">
<span t-if="doc.state not in ['draft','sent']">Order # </span>
<span t-if="doc.state in ['draft','sent']">Quotation # </span>
</t>
<t t-if="env.context.get('proforma', False) or is_pro_forma">
<span>Pro-Forma Invoice # </span>
</t>
<span t-field="doc.name"/>
</h2>
<div class="row mt32 mb32" id="informations">
<div t-if="doc.client_order_ref" class="col-auto mw-100 mb-2">
<strong>Your Reference:</strong>
<p class="m-0" t-field="doc.client_order_ref"/>
</div>
<div t-if="doc.confirmation_date and doc.state not in ['draft','sent']" class="col-auto mw-100 mb-2">
<strong>Date Ordered:</strong>
<p class="m-0" t-field="doc.confirmation_date"/>
</div>
<div t-if="doc.date_order and doc.state in ['draft','sent']" class="col-auto mw-100 mb-2">
<strong>Quotation Date:</strong>
<p class="m-0" t-field="doc.date_order"/>
</div>
<div t-if="doc.user_id.name" class="col-auto mw-100 mb-2">
<strong>Salesperson:</strong>
<p class="m-0" t-field="doc.user_id"/>
</div>
<div name="payment_term" t-if="doc.payment_term_id" class="col-auto mw-100 mb-2">
<strong>Payment Terms:</strong>
<p class="m-0" t-field="doc.payment_term_id"/>
</div>
<div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-auto mw-100 mb-2">
<strong>Expiration Date:</strong>
<p class="m-0" t-field="doc.validity_date"/>
</div>
</div>
<!-- Is there a discount on at least one line? -->
<t t-set="display_discount" t-value="any([l.discount for l in doc.order_line])"/>
<table class="table table-sm o_main_table">
<thead>
<tr>
<!-- TODO: remove in master -->
<t t-set="colspan" t-value="5"/>
<th class="text-left">Description</th>
<th class="text-right">Quantity</th>
<th class="text-right">Unit Price</th>
<th class="text-right">Taxes</th>
<th t-if="display_discount" class="text-right" groups="sale.group_discount_per_so_line">
<span>Disc.(%)</span>
<!-- TODO: remove in master -->
<t t-set="colspan" t-value="colspan+1"/>
</th>                        
<th class="text-right">
<t groups="account.group_show_line_subtotals_tax_excluded">Amount</t>
<t groups="account.group_show_line_subtotals_tax_included">Total Price</t>
</th>
</tr>
</thead>
<tbody class="sale_tbody">
<t t-set="current_subtotal" t-value="0"/>
<t t-foreach="doc.order_line" t-as="line">
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
<tr t-att-class="'bg-200 font-weight-bold o_line_section' if line.display_type == 'line_section' else 'font-italic o_line_note' if line.display_type == 'line_note' else ''">
<t t-if="not line.display_type">
<td><span t-field="line.name"/></td>
<td class="text-right">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom" groups="uom.group_uom"/>
</td>
<td class="text-right">
<span t-field="line.price_unit"/>
</td>
<td class="text-right">
<span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_id))"/>
</td>
<td t-if="display_discount" class="text-right" groups="sale.group_discount_per_so_line">
<span t-field="line.discount"/>
</td>                                
<td class="text-right o_price_total">
<span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
</td>
</t>
<t t-if="line.display_type == 'line_section'">
<td colspan="99">
<span t-field="line.name"/>
</td>
<t t-set="current_section" t-value="line"/>
<t t-set="current_subtotal" t-value="0"/>
</t>
<t t-if="line.display_type == 'line_note'">
<td colspan="99">
<span t-field="line.name"/>
</td>
</t>
</tr>
<t t-if="current_section and (line_last or doc.order_line[line_index+1].display_type == 'line_section')">
<tr class="is-subtotal text-right">
<td colspan="99">
<strong class="mr16">Subtotal</strong>
<span
t-esc="current_subtotal"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'
/>
</td>
</tr>
</t>
</t>
</tbody>
</table>
<div class="clearfix">
<div id="total" class="row" name="total">
<div t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
<table class="table table-sm">
<tr class="border-black o_subtotal" style="">
<td><strong>Subtotal</strong></td>
<td class="text-right">
<span t-field="doc.amount_untaxed"/>
</td>
</tr>
<t t-foreach="doc.amount_by_group" t-as="amount_by_group">
<tr style="">
<t t-if="amount_by_group[3] == 1 and doc.amount_untaxed == amount_by_group[2]">
<td>
<span t-esc="amount_by_group[0]"/>
<span>&amp;nbsp;<span>on</span>&amp;nbsp;<t t-esc="amount_by_group[2]" t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/></span>
</td>
<td class="text-right o_price_total">
<span t-esc="amount_by_group[1]"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
</td>
</t>
<t t-else ="">
<td>
<span t-esc="amount_by_group[0]"/>
</td>
<td class="text-right o_price_total">
<span t-esc="amount_by_group[1]"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
</td>
</t>
</tr>
</t>
<tr class="border-black o_total">
<td><strong>Total</strong></td>
<td class="text-right">
<span t-field="doc.amount_total"/>
</td>
</tr>
</table>
</div>
</div>
</div>
<p t-field="doc.note" />
<p t-if="doc.payment_term_id.note">
<span t-field="doc.payment_term_id.note"/>
</p>
<p id="fiscal_position_remark" t-if="doc.fiscal_position_id and doc.fiscal_position_id.sudo().note">
<strong>Fiscal Position Remark:</strong>
<span t-field="doc.fiscal_position_id.sudo().note"/>
</p>
<div t-if="doc.signature" class="mt32 ml16 mr16" name="signature">
<div class="offset-8">
<strong>Signature</strong>
</div>
<div class="offset-8">
<img t-att-src="image_data_uri(doc.signature)" style="max-height: 4cm; max-width: 8cm;"/>
</div>
<div class="offset-8 text-center">
<p t-field="doc.signed_by"/>
</div>
</div>
<div class="oe_structure"/>
</div>
</xpath>
</template>
</data>
</openerp>

Add custom field to Sale Order form view

class CustomSaleOrder(models.Model):
_inherit = 'sale.order'
my_custom_field = fields.Char(string='My Field')
<record id="view_sale_order_form_custom_inherit" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_shipping_id']" position="after">
<field name="my_custom_field"/>            
</xpath>
</field>
</record>

Add custom field to Sale Order tree

<record model="ir.ui.view" id="view_sale_order_tree_custom_inherit">
<field name="name">sale.order.tree.with.onboarding.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_quotation_tree_with_onboarding"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='amount_total']" position="after">
<field name="my_custom_field"/>
</xpath>
</field>
</record>

Leave a Comment

Your email address will not be published.