19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -2,7 +2,7 @@
<odoo>
<record id="digest_digest_view_form" model="ir.ui.view">
<field name="name">digest.digest.view.form.inherit.sale.order</field>
<field name="name">digest.digest.view.form.inherit.sale_management</field>
<field name="model">digest.digest</field>
<field name="priority">10</field>
<field name="inherit_id" ref="digest.digest_digest_view_form" />

View file

@ -6,55 +6,26 @@
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="sale.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='sale_config_online_confirmation_pay']" position="after">
<div class="col-12 col-lg-6 o_setting_box" id="standardized_offers_setting">
<div class="o_setting_left_pane">
<field name="group_sale_order_template"/>
<field name="module_sale_quotation_builder" invisible="1"/>
</div>
<div class="o_setting_right_pane">
<label for="group_sale_order_template"/>
<a href="https://www.odoo.com/documentation/16.0/applications/sales/sales/send_quotations/quote_template.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Create standardized offers with default products
<setting id="online_signature" position="after">
<setting id="standardized_offers_setting"
company_dependent="1"
documentation="/applications/sales/sales/send_quotations/quote_template.html"
help="Create standardized offers with default products">
<field name="group_sale_order_template"/>
<div class="content-group" invisible="not group_sale_order_template">
<div class="mt16">
<label for="company_so_template_id" class="o_light_label mr8"/>
<field name="company_so_template_id" class="oe_inline"/>
</div>
<div class="content-group" attrs="{'invisible': [('group_sale_order_template', '=', False)]}">
<div class="mt16">
<label for="company_so_template_id" class="o_light_label me-2"/>
<field name="company_so_template_id" class="oe_inline"/>
</div>
<div class="mt8">
<button name="%(sale_management.sale_order_template_action)d" icon="fa-arrow-right" type="action" string="Quotation Templates" class="btn-link"/>
</div>
<div class="mt8">
<button name="%(sale_management.sale_order_template_action)d" icon="oi-arrow-right" type="action" string="Quotation Templates" class="btn-link"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box"
id="design_quotation_template_setting"
attrs="{'invisible': [('group_sale_order_template','=',False)]}">
<div class="o_setting_left_pane">
<field name="module_sale_quotation_builder"/>
</div>
<div class="o_setting_right_pane">
<label for="module_sale_quotation_builder"/>
<div class="text-muted">
Design your quotation templates using building blocks<br/>
<em attrs="{'invisible': [('module_sale_quotation_builder','=',False)]}">Warning: this option will install the Website app.</em>
</div>
</div>
</div>
</xpath>
</field>
</record>
<record id="res_config_settings_view_form_inherit_sale_management" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.sale.management</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="sale.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@data-key='sale_management']" position="attributes">
<attribute name="class">app_settings_block</attribute>
</xpath>
</setting>
</setting>
<app name="sale_management" position="attributes">
<attribute name="notApp">0</attribute>
</app>
</field>
</record>

View file

@ -7,7 +7,7 @@
<search string="Search Quotation Template">
<field name="name"/>
<filter string="Archived" name="inactive" domain="[('active','=', False)]"/>
<group expand="1" string="Group By">
<group>
<filter string="Company" name="company_id" context="{'group_by': 'company_id'}" groups="base.group_multi_company"/>
</group>
</search>
@ -17,12 +17,11 @@
<record id="sale_order_template_view_form" model="ir.ui.view">
<field name="name">sale.order.template.form</field>
<field name="model">sale.order.template</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Quotation Template">
<sheet>
<div name="button_box" class="oe_button_box"/>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<div class="oe_title" name="sale_order_template_title">
<label for="name" id="sale_order_template_title"/>
<h1>
@ -32,25 +31,35 @@
<group>
<group name="sale_info">
<field name="active" invisible="1"/>
<label for="number_of_days" string="Quotation expires after"/>
<label for="number_of_days" string="Quotation Validity"/>
<div id="number_of_days">
<field name="number_of_days" style="width: 3rem;"/>
<div class="d-inline-block">days</div>
</div>
<label for="require_signature" string="Online confirmation"/>
<div>
<field name="require_signature" class="oe_inline"/>
<span>Signature</span>
<field name="require_payment" class="oe_inline ms-3"/>
<span>Payment</span>
</div>
<field name="mail_template_id" context="{'default_model': 'sale.order'}"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company" placeholder="Visible to all"/>
<field name="journal_id"/>
</group>
<group name="so_confirmation">
<field name="require_signature"/>
<label for="require_payment"/>
<div id="require_payment" class="o_row">
<field name="require_payment" class="oe_inline"/>
<span invisible="not require_payment">of</span>
<field name="prepayment_percent"
invisible="not require_payment"
widget="percentage"
class="oe_inline"/>
</div>
</group>
</group>
<notebook name="main_book">
<page string="Lines" name="order_lines">
<field name="sale_order_template_line_ids" widget="section_and_note_one2many">
<field
name="sale_order_template_line_ids"
widget="so_template_line_o2m"
options="{ 'subsections': True }"
>
<form string="Quotation Template Lines">
<!--
We need the sequence field to be here for new lines to be added at the correct position.
@ -58,11 +67,9 @@
-->
<field name="sequence" invisible="1"/>
<field name="display_type" invisible="1"/>
<field name="product_uom_category_id" invisible="1"/>
<field name="company_id" invisible="1"/>
<group attrs="{'invisible': [('display_type', '!=', False)]}">
<group invisible="display_type">
<group>
<field name="product_id" attrs="{'required': [('display_type', '=', False)]}"/>
<field name="product_id" required="not display_type"/>
<label for="product_uom_qty"/>
<div>
<field name="product_uom_qty" class="oe_inline"/>
@ -70,54 +77,41 @@
</group>
</group>
<notebook colspan="4" name="description">
<page string="Description" name="order_description" attrs="{'invisible': [('display_type', '!=', False)]}">
<page string="Description" name="order_description" invisible="display_type">
<field name="name" />
</page>
<page string="Section" name="order_section" attrs="{'invisible': [('display_type', '!=', 'line_section')]}">
<page string="Section" name="order_section" invisible="display_type != 'line_section'">
<field name="name" />
</page>
<page string="Note" name="order_note" attrs="{'invisible': [('display_type', '!=', 'line_note')]}">
<page string="Note" name="order_note" invisible="display_type != 'line_note'">
<field name="name" />
</page>
</notebook>
</form>
<tree string="Quotation Template Lines" editable="bottom">
<list string="Quotation Template Lines" editable="bottom">
<control>
<create name="add_product_control" string="Add a product"/>
<create name="add_section_control" string="Add a section" context="{'default_display_type': 'line_section'}"/>
<create name="add_note_control" string="Add a note" context="{'default_display_type': 'line_note'}"/>
</control>
<field name="display_type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="display_type" column_invisible="True"/>
<field name="is_optional" column_invisible="True"/>
<field name="sequence" widget="handle"/>
<field name="product_id"/>
<field name="name"/>
<field name="product_uom_qty"/>
<field name="product_uom_category_id" invisible="1"/>
<field
name="product_uom_id"
groups="uom.group_uom"
attrs="{'required': [('display_type', '=', False)]}"
/>
</tree>
</field>
</page>
<page string="Optional Products" name="optional_products">
<field name="sale_order_template_option_ids">
<tree string="Quotation Template Lines" editable="bottom">
<field name="product_id"/>
<field name="name"/>
<field name="quantity"/>
<field name="product_uom_category_id" invisible="1"/>
<field name="uom_id" groups="uom.group_uom"/>
<field name="company_id" invisible="1"/>
</tree>
required="not display_type"/>
</list>
</field>
</page>
<page string="Terms &amp; Conditions" name="terms_and_conditions">
<field name="note" nolabel="1"
placeholder="The Administrator can set default Terms &amp; Conditions in Sales Settings. Terms set here will show up instead if you select this quotation template."/>
<field
name="note"
nolabel="1"
placeholder="The Administrator can set default Terms &amp; Conditions in Sales Settings. Terms set here will show up instead if you select this quotation template."/>
</page>
</notebook>
</sheet>
@ -126,22 +120,21 @@
</record>
<record id="sale_order_template_view_tree" model="ir.ui.view">
<field name="name">sale.order.template.tree</field>
<field name="name">sale.order.template.list</field>
<field name="model">sale.order.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Quotation Template">
<list string="Quotation Template">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</list>
</field>
</record>
<record id="sale_order_template_action" model="ir.actions.act_window">
<field name="name">Quotation Templates</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sale.order.template</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your quotation template

View file

@ -6,106 +6,26 @@
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<page name="order_lines" position="after">
<page string="Optional Products"
name="optional_products"
attrs="{'invisible': [('state', 'not in', ['draft', 'sent'])]}">
<field name="sale_order_option_ids" mode="tree,form,kanban">
<form string="Optional Products">
<group>
<field name="product_id"
domain="[('sale_ok', '=', True), '|', ('company_id', '=', False), ('company_id', '=', parent.company_id)]"/>
<field name="name"/>
<field name="quantity"/>
<field name="product_uom_category_id" invisible="1"/>
<field name="uom_id" groups="uom.group_uom"/>
<field name="price_unit"/>
<field name="discount" groups="product.group_discount_per_so_line"/>
<field name="is_present" />
</group>
</form>
<kanban class="o_kanban_mobile">
<field name="product_id"/>
<field name="quantity"/>
<field name="uom_id" groups="uom.group_uom"/>
<field name="price_unit"/>
<field name="is_present" />
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="row">
<div class="col-10">
<strong>
<span>
<t t-out="record.product_id.value"/>
</span>
</strong>
</div>
<div class="col-2">
<button name="button_add_to_order"
class="btn btn-link oe_link fa fa-shopping-cart"
title="Add to order lines"
type="object"
attrs="{'invisible': [('is_present', '=', True)]}"/>
</div>
</div>
<div class="row">
<div class="col-12 text-muted">
<span>
Quantity:
<t t-out="record.quantity.value"/>
<t t-out="record.uom_id.value" groups="uom.group_uom"/>
</span>
</div>
</div>
<div class="row">
<div class="col-12 text-muted">
<span>
Unit Price:
<t t-out="record.price_unit.value"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
<tree string="Sales Quotation Template Lines"
editable="bottom"
decoration-success="is_present == True">
<control>
<create name="add_product_control" string="Add a product"/>
</control>
<field name="sequence" widget="handle"/>
<field name="product_id"
domain="[('sale_ok', '=', True), '|', ('company_id', '=', False), ('company_id', '=', parent.company_id)]"/>
<field name="name" optional="show"/>
<field name="quantity"/>
<field name="uom_id" string="UoM" groups="uom.group_uom" optional="show"/>
<field name="product_uom_category_id" invisible="1"/>
<field name="price_unit"/>
<field name="discount"
string="Disc.%"
groups="product.group_discount_per_so_line"
optional="show"/>
<field name="is_present" invisible="1" />
<button name="button_add_to_order"
type="object"
class="oe_link"
icon="fa-shopping-cart"
title="Add to order lines"
attrs="{'invisible': [('is_present', '=', True)]}"/>
</tree>
</field>
</page>
</page>
<field name="partner_shipping_id" position="after">
<field name="sale_order_template_id"
<field
name="sale_order_template_id"
options="{'no_create': True}"
groups="sale_management.group_sale_order_template"
/>
readonly="state in ['cancel', 'sale']"
groups="sale_management.group_sale_order_template"/>
</field>
<xpath expr="//form//div[@name='invoice_lines']" position="before">
<group>
<field
name="is_optional"
invisible="display_type not in ['line_section', 'line_subsection']"
readonly="1"
/>
</group>
</xpath>
<xpath expr="//list/field[@name='linked_virtual_id']" position="after">
<field name="is_optional" column_invisible="True"/>
</xpath>
</field>
</record>

View file

@ -1,100 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="sale_order_portal_optional_product_quantity" name="Order Quantity">
<div t-if="line._can_be_edited_on_portal()" class="d-inline-flex">
<div class="input-group js_quantity_container pull-right">
<span class="d-print-none input-group-text d-none d-md-inline-block">
<a
title="Remove one"
aria-label="Remove one"
href="#"
t-att-class="'opacity-50' if line.product_uom_qty == 0 else 'js_update_line_json'"
t-att-data-line-id="line.id"
t-att-data-remove="True"
>
<span class="fa fa-minus"/>
</a>
</span>
<input
type="text"
class="js_quantity form-control"
t-att-data-line-id="line.id"
t-att-value="int(line.product_uom_qty) or '0'"
/>
<span class="d-print-none input-group-text d-none d-md-inline-block">
<a
title="Add one"
aria-label="Add one"
class="js_update_line_json"
href="#"
t-att-data-line-id="line.id"
>
<span class="fa fa-plus"/>
</a>
</span>
</div>
<div class="ms-1 align-self-center">
<span t-field="line.product_uom_id"/>
</div>
</div>
<div t-else="">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom_id"/>
</div>
</template>
<template id="sale_order_portal_content_inherit_sale_management" name="Order Options" inherit_id="sale.sale_order_portal_content">
<xpath expr="//section[@id='details']//t[@t-set='display_discount']" position="after">
<t t-set="display_remove" t-value="sale_order.state in ('draft', 'sent') and any(line.sale_order_option_ids for line in sale_order.order_line)"/>
<xpath expr="//td[@name='td_product_quantity']/div[@id='quote_qty']" position="replace">
<t t-call="sale_management.sale_order_portal_optional_product_quantity"/>
</xpath>
<xpath expr="//section[@id='details']//table[@id='sales_order_table']/thead/tr" position="inside">
<!-- add blank Tr in thead for layout conciseness -->
<th t-if="display_remove">
</th>
<xpath expr="//td[@name='td_combo_quantity']/div[@id='quote_qty']" position="replace">
<t t-call="sale_management.sale_order_portal_optional_product_quantity"/>
</xpath>
<xpath expr="//section[@id='details']//t[@t-if='not line.display_type']" position="inside">
<td class="text-center" t-if="display_remove">
<a t-att-data-line-id="line.id" t-att-data-unlink="True" href="#" class="mb8 js_update_line_json d-print-none" t-if="sale_order.state in ('draft', 'sent') and line.sale_order_option_ids" aria-label="Remove" title="Remove">
<span class="fa fa-trash-o"></span>
</a>
</td>
</xpath>
<xpath expr="//section[@id='signature']" position="after">
<t t-if="any((not option.is_present) for option in sale_order.sale_order_option_ids)">
<section>
<h3>Options</h3>
<t t-set="display_discount" t-value="True in [option.discount > 0 for option in sale_order.sale_order_option_ids]"/>
<table class="table table-sm">
<thead>
<tr>
<th class="text-start">Product</th>
<th t-if="display_discount" class="text-end">Disc.%
</th>
<th class="text-end">Unit Price</th>
<th t-if="sale_order.state in ['draft', 'sent'] and report_type == 'html'"></th>
</tr>
</thead>
<tbody>
<tr t-foreach="sale_order.sale_order_option_ids" t-as="option">
<t t-if="not option.is_present">
<td>
<div t-field="option.name"/>
</td>
<td t-if="display_discount" class="text-end">
<strong t-if="option.discount" class="text-info">
<t t-out="((option.discount % 1) and '%s' or '%d') % option.discount"/>%
</strong>
</td>
<td>
<strong class="text-end">
<div t-field="option.price_unit"
t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'
t-att-style="option.discount and 'text-decoration: line-through' or None"
t-att-class="option.discount and 'text-danger' or None"/>
<div t-if="option.discount">
<t t-out="(1-option.discount / 100.0) * option.price_unit" t-options='{"widget": "monetary", "display_currency": sale_order.pricelist_id.currency_id}'/>
</div>
</strong>
</td>
<td class="text-center" t-if="sale_order.state in ['draft', 'sent'] and report_type == 'html'">
<a t-att-data-option-id="option.id" href="#" class="mb8 js_add_optional_products d-print-none" aria-label="Add to cart" title="Add to cart">
<span class="fa fa-shopping-cart"/>
</a>
</td>
</t>
</tr>
</tbody>
</table>
</section>
</t>
</xpath>
<xpath expr="//section[@id='details']//div[@id='quote_qty']" position="replace">
<t t-if="sale_order.state in ['draft', 'sent'] and line.sale_order_option_ids">
<div class="input-group js_quantity_container pull-right">
<span class="d-print-none input-group-text d-none d-md-inline-block">
<a t-att-data-line-id="line.id" t-att-data-remove="True" href="#" class="js_update_line_json" aria-label="Remove one" title="Remove one">
<span class="fa fa-minus"/>
</a>
</span>
<!-- TODO add uom in this case too -->
<input type="text" class="js_quantity form-control" t-att-data-line-id="line.id" t-att-value="line.product_uom_qty"/>
<span class="d-print-none input-group-text d-none d-md-inline-block">
<a t-att-data-line-id="line.id" href="#" class="js_update_line_json" aria-label="Add one" title="Add one">
<span class="fa fa-plus"/>
</a>
</span>
</div>
</t>
<t t-else="">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom"/>
</t>
</xpath>
</template>
</odoo>