[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:
committed by
Victor Feyens
parent
2689915e3f
commit
52b87b6948
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user