[IMP] product: Improve pricelist item form view

Purpose of the task is to Improve the current pricelist line
form view for clarity.

SPECIFICATIONS:

 - Move the price computation on top and apply on at bottom.
 - Improve the formula view and calculate dynamic tips based
on formula value.

closes odoo/odoo#63733

Taskid: 2373068
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit is contained in:
Kamesh Patel
2021-02-03 15:41:27 +00:00
committed by Victor Feyens
parent 2689915e3f
commit 52b87b6948
2 changed files with 110 additions and 78 deletions
+36 -4
View File
@@ -20,7 +20,7 @@ class Pricelist(models.Model):
name = fields.Char('Pricelist Name', required=True, translate=True)
active = fields.Boolean('Active', default=True, help="If unchecked, it will allow you to hide the pricelist without removing it.")
item_ids = fields.One2many(
'product.pricelist.item', 'pricelist_id', 'Pricelist Items',
'product.pricelist.item', 'pricelist_id', 'Pricelist Rules',
copy=True)
currency_id = fields.Many2one('res.currency', 'Currency', default=_get_default_currency_id, required=True)
company_id = fields.Many2one('res.company', 'Company')
@@ -403,7 +403,9 @@ class PricelistItem(models.Model):
price_surcharge = fields.Float(
'Price Surcharge', digits='Product Price',
help='Specify the fixed amount to add or substract(if negative) to the amount calculated with the discount.')
price_discount = fields.Float('Price Discount', default=0, digits=(16, 2))
price_discount = fields.Float(
'Price Discount', default=0, digits=(16, 2),
help="You can apply a mark-up by setting a negative discount.")
price_round = fields.Float(
'Price Rounding', digits='Product Price',
help="Sets the price so that it is a multiple of this value.\n"
@@ -429,10 +431,12 @@ class PricelistItem(models.Model):
"The displayed value depends on the timezone set in your preferences.")
compute_price = fields.Selection([
('fixed', 'Fixed Price'),
('percentage', 'Percentage (discount)'),
('percentage', 'Discount'),
('formula', 'Formula')], index=True, default='fixed', required=True)
fixed_price = fields.Float('Fixed Price', digits='Product Price')
percent_price = fields.Float('Percentage Price')
percent_price = fields.Float(
'Percentage Price',
help="You can apply a mark-up by setting a negative discount.")
# functional fields used for usability purposes
name = fields.Char(
'Name', compute='_get_pricelist_item_name_price',
@@ -440,6 +444,7 @@ class PricelistItem(models.Model):
price = fields.Char(
'Price', compute='_get_pricelist_item_name_price',
help="Explicit rule name for this pricelist line.")
rule_tip = fields.Char(compute='_compute_rule_tip')
@api.constrains('base_pricelist_id', 'pricelist_id', 'base')
def _check_recursion(self):
@@ -497,6 +502,33 @@ class PricelistItem(models.Model):
else:
item.price = _("%(percentage)s %% discount and %(price)s surcharge", percentage=item.price_discount, price=item.price_surcharge)
@api.depends_context('lang')
@api.depends('compute_price', 'price_discount', 'price_surcharge', 'base', 'price_round')
def _compute_rule_tip(self):
base_selection_vals = {elem[0]: elem[1] for elem in self._fields['base']._description_selection(self.env)}
self.rule_tip = False
for item in self:
if item.compute_price != 'formula':
continue
base_amount = 100
discount_factor = (100 - item.price_discount) / 100
discounted_price = base_amount * discount_factor
if item.price_round:
discounted_price = tools.float_round(discounted_price, precision_rounding=item.price_round)
surcharge = tools.format_amount(item.env, item.price_surcharge, item.currency_id)
item.rule_tip = _(
"%(base)s with a %(discount)s %% discount and %(surcharge)s extra fee\n"
"Example: %(amount)s * %(discount_charge)s + %(price_surcharge)s → %(total_amount)s",
base=base_selection_vals[item.base],
discount=item.price_discount,
surcharge=surcharge,
amount=tools.format_amount(item.env, 100, item.currency_id),
discount_charge=discount_factor,
price_surcharge=surcharge,
total_amount=tools.format_amount(
item.env, discounted_price + item.price_surcharge, item.currency_id),
)
@api.onchange('compute_price')
def _onchange_compute_price(self):
if self.compute_price != 'fixed':
@@ -54,7 +54,7 @@
<field name="model">product.pricelist.item</field>
<field name="priority">100</field>
<field name="arch" type="xml">
<tree string="Pricelist Items" editable="bottom">
<tree string="Pricelist Rules" editable="bottom">
<!-- Scope = coming from a product/product template -->
<field name="pricelist_id" string="Pricelist" options="{'no_create_edit':1, 'no_open': 1}"/>
<field name="name" string="Applied On"/>
@@ -91,79 +91,79 @@
<field name="name">product.pricelist.item.form</field>
<field name="model">product.pricelist.item</field>
<field name="arch" type="xml">
<form string="Pricelist Items">
<form string="Pricelist Rule">
<sheet>
<h1><field name="name"/></h1>
<group>
<group name="pricelist_rule_target">
<field name="applied_on" widget="radio"/>
<field name="categ_id" attrs="{
'invisible':[('applied_on', '!=', '2_product_category')],
'required':[('applied_on', '=', '2_product_category')]}"
options="{'no_create':1}"/>
<field name="product_tmpl_id" attrs="{
'invisible':[('applied_on', '!=', '1_product')],
'required':[('applied_on', '=', '1_product')]}"
options="{'no_create':1}"/>
<field name="product_id" attrs="{
'invisible':[('applied_on', '!=', '0_product_variant')],
'required':[('applied_on', '=', '0_product_variant')]}"
options="{'no_create':1}"/>
</group>
<group name="pricelist_rule_limits">
<field name="min_quantity"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<group name="pricelist_rule_related" groups="base.group_no_one">
<!-- Infos from the pricelist for UI rendering (monetary fields, ...) -->
<field name="pricelist_id" invisible="1"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<group string="Price Computation" name="pricelist_rule_computation" groups="product.group_sale_pricelist">
<group name="pricelist_rule_method">
<field name="compute_price" string="Compute Price" widget="radio"/>
</group>
<group name="pricelist_rule_base">
<field name="fixed_price" attrs="{'invisible':[('compute_price', '!=', 'fixed')]}"/>
<label for="percent_price" attrs="{'invisible':[('compute_price', '!=', 'percentage')]}"/>
<div attrs="{'invisible':[('compute_price', '!=', 'percentage')]}">
<field name="percent_price"
class="oe_inline"
attrs="{'invisible':[('compute_price', '!=', 'percentage')]}"/>
%%
</div>
<field name="base" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<field name="base_pricelist_id" attrs="{
'invisible': ['|', ('compute_price', '!=', 'formula'), ('base', '!=', 'pricelist')],
'required': [('compute_price', '=', 'formula'), ('base', '=', 'pricelist')],
'readonly': [('base', '!=', 'pricelist')]}"/>
</group>
</group>
<div class="oe_grey" groups="uom.group_uom">
<p>The computed price is expressed in the default Unit of Measure of the product.</p>
</div>
<group name="pricelist_rule_advanced" col="6" attrs="{'invisible':[('compute_price', '!=', 'formula')]}" groups="product.group_sale_pricelist">
<label for="base" string="New Price = "/>
<div>
<span attrs="{'invisible':[('base', '!=', 'list_price')]}">Sales Price - </span>
<span attrs="{'invisible':[('base', '!=', 'standard_price')]}">Cost - </span>
<span attrs="{'invisible':[('base', '!=', 'pricelist')]}">Other Pricelist - </span>
</div>
<label for="price_discount"/>
<div class="o_row">
<field name="price_discount"/>
<span>%%</span>
</div>
<label string=" + " for="price_surcharge"/>
<field name="price_surcharge" nolabel="1"/>
<group name="pricelist_rule_computation" groups="product.group_sale_pricelist" string="Price Computation">
<group name="pricelist_rule_method">
<field name="compute_price" string="Computation" widget="radio"/>
</group>
<div>
<div class="alert alert-info" role="alert" groups="uom.group_uom">
The computed price is expressed in the default Unit of Measure of the product.
</div>
</div>
</group>
<group name="pricelist_rule_base" groups="product.group_sale_pricelist">
<group>
<field name="fixed_price" widget="monetary" attrs="{'invisible':[('compute_price', '!=', 'fixed')]}"/>
<label for="percent_price" string="Discount" attrs="{'invisible':[('compute_price', '!=', 'percentage')]}"/>
<div class="o_row" attrs="{'invisible':[('compute_price', '!=', 'percentage')]}">
<field name="percent_price" class="oe_inline" attrs="{'invisible':[('compute_price', '!=', 'percentage')]}"/>%%
</div>
<field name="base" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<field name="base_pricelist_id" attrs="{
'invisible': ['|', ('compute_price', '!=', 'formula'), ('base', '!=', 'pricelist')],
'required': [('compute_price', '=', 'formula'), ('base', '=', 'pricelist')],
'readonly': [('base', '!=', 'pricelist')]}"/>
<label for="price_discount" string="Discount" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<div class="o_row" attrs="{'invisible':[('compute_price', '!=', 'formula')]}">
<field name="price_discount"/>
<span>%%</span>
</div>
<field name="price_surcharge" widget="monetary" string="Extra Fee" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<field name="price_round" string="Rounding Method" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<label string="Margins" for="price_min_margin" attrs="{'invisible':[('compute_price', '!=', 'formula')]}"/>
<div class="o_row" attrs="{'invisible':[('compute_price', '!=', 'formula')]}">
<field name="price_min_margin" string="Min. Margin" class="oe_inline" widget="monetary" nolabel="1"/>
<i class="fa fa-long-arrow-right mx-2 oe_edit_only" aria-label="Arrow icon" title="Arrow"/>
<field name="price_max_margin" string="Max. Margin" class="oe_inline" widget="monetary" nolabel="1"/>
</div>
</group>
<group>
<div class="alert alert-info" role="alert" style="white-space: pre;" attrs="{'invisible':[('compute_price', '!=', 'formula')]}">
<field name="rule_tip"/>
</div>
</group>
</group>
<field name="price_round" string="Rounding Method"/>
<field name="price_min_margin" string="Min. Margin"/>
<field name="price_max_margin" string="Max. Margin"/>
</group>
<group string="Conditions">
<group name="pricelist_rule_target">
<field name="applied_on" widget="radio"/>
<field name="categ_id" options="{'no_create':1}" attrs="{
'invisible':[('applied_on', '!=', '2_product_category')],
'required':[('applied_on', '=', '2_product_category')]}"/>
<field name="product_tmpl_id" options="{'no_create':1}" attrs="{
'invisible':[('applied_on', '!=', '1_product')],
'required':[('applied_on', '=', '1_product')]}"/>
<field name="product_id" options="{'no_create':1}" attrs="{
'invisible':[('applied_on', '!=', '0_product_variant')],
'required':[('applied_on', '=', '0_product_variant')]}"/>
</group>
<group name="pricelist_rule_limits">
<field name="min_quantity"/>
<label for="date_start" string="Validity"/>
<div class="o_row">
<field name="date_start" widget="daterange" options='{"related_end_date": "date_end"}'/>
<i class="fa fa-long-arrow-right mx-2 oe_edit_only" aria-label="Arrow icon" title="Arrow"/>
<field name="date_end" widget="daterange" options='{"related_start_date": "date_start"}'/>
</div>
</group>
<group name="pricelist_rule_related" groups="base.group_no_one">
<field name="pricelist_id" invisible="1"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
</sheet>
</form>
</field>
@@ -238,7 +238,7 @@
<notebook>
<page name="pricelist_rules" string="Price Rules">
<field name="item_ids" nolabel="1" context="{'default_base':'list_price'}">
<tree string="Pricelist Items" editable="bottom">
<tree string="Pricelist Rules" editable="bottom">
<field name="product_tmpl_id" string="Products" required="1"/>
<field name="product_id" string="Variants"
groups="product.group_product_variant"
@@ -284,7 +284,7 @@
-->
<field name="item_ids" position="replace">
<field name="item_ids" nolabel="1" context="{'default_base':'list_price'}" groups="product.group_product_pricelist">
<tree string="Pricelist Items">
<tree string="Pricelist Rules">
<field name="name" string="Applicable On"/>
<field name="min_quantity"/>
<field name="price" string="Price"/>