Skip to content

Commit 3849260

Browse files
committed
[IMP{] sale_ux: implement pricelist management and display in product forms
closes #1592 Related: ingadhoc/product#846 Signed-off-by: matiasperalta1 <mnp@adhoc.com.ar>
1 parent d628072 commit 3849260

File tree

9 files changed

+113
-1
lines changed

9 files changed

+113
-1
lines changed

sale_ux/README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Several Improvements to sales:
4646
#. When duplicating a Sale Order, a message is logged in the new order indicating the origin.
4747
#. Allows selecting default values to assign price lists by companies and by user with the field `specific_property_product_pricelist`. It also ensures that when creating a contact, if it is not defined, it will not be set for the company you are currently on (we consider this to be an Odoo bug).
4848
#. Prevents writing in certain fields in blocked sales orders
49+
#. Displays all pricelists information directly on product forms. Shows a computed table with all pricelists (that have "Show in products" enabled) and their calculated prices for the product. Hides the standard "Pricelist Rules" field and adds a "Show in products" checkbox on pricelists to control visibility. Non-manager salespeople have read-only access to pricelist forms.
4950

5051
Installation
5152
============

sale_ux/__manifest__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
"views/res_config_settings_views.xml",
4848
"views/account_fiscal_position_views.xml",
4949
"views/product_template_views.xml",
50+
"views/product_pricelist_views.xml",
51+
"views/product_template_pricelist_views.xml",
5052
"data/ir_config_parameter_data.xml",
5153
"data/ir_cron.xml",
5254
],

sale_ux/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from . import res_config_settings
1010
from . import product_product
1111
from . import product_template
12+
from . import product_pricelist
1213
from . import account_fiscal_position
1314
from . import res_partner
1415
from . import crm_team
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
##############################################################################
2+
# For copyright and license notices, see __manifest__.py file in module root
3+
# directory
4+
##############################################################################
5+
from odoo import api, fields, models
6+
7+
8+
class ProductPricelist(models.Model):
9+
_inherit = "product.pricelist"
10+
11+
price = fields.Monetary(
12+
compute="_compute_price",
13+
help="Price for product specified on the context",
14+
)
15+
show_products = fields.Boolean(
16+
"Show in products",
17+
default=True,
18+
help="By selecting it allows you to display the pricelist with the price of that product in the products",
19+
)
20+
21+
def _compute_price(self):
22+
self = self.sudo()
23+
active_id = model = False
24+
if "pricelist_product_id" in self.env.context:
25+
active_id = self.env.context.get("pricelist_product_id")
26+
model = "product.product"
27+
elif "pricelist_template_id" in self.env.context:
28+
active_id = self.env.context.get("pricelist_template_id")
29+
model = "product.template"
30+
else:
31+
self.price = 0.0
32+
33+
if active_id and model:
34+
product = self.env[model].browse(active_id)
35+
for rec in self:
36+
contextual_price = product.with_context(pricelist=rec.id)._get_contextual_price()
37+
rec.sudo().write({"price": contextual_price})
38+
39+
@api.model
40+
def _get_view(self, view_id=None, view_type="form", **options):
41+
arch, view = super()._get_view(view_id, view_type, **options)
42+
if view_type == "form":
43+
if (
44+
self.env.user.has_group("sales_team.group_sale_salesman")
45+
or self.env.user.has_group("sales_team.group_sale_salesman_all_leads")
46+
) and not self.env.user.has_group("sales_team.group_sale_manager"):
47+
fields = arch.xpath("//form")
48+
for node in fields:
49+
node.set("edit", "false")
50+
return arch, view

sale_ux/models/product_product.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
import logging
22

3-
from odoo import api, models
3+
from odoo import api, fields, models
44

55
_logger = logging.getLogger(__name__)
66

77

88
class ProductProduct(models.Model):
99
_inherit = "product.product"
1010

11+
pricelist_ids = fields.One2many(
12+
"product.pricelist",
13+
compute="_compute_pricelist_ids",
14+
string="Pricelists",
15+
)
16+
17+
def _compute_pricelist_ids(self):
18+
for rec in self:
19+
rec.pricelist_ids = rec.pricelist_ids.search([("show_products", "=", True)])
20+
rec.pricelist_ids.with_context(pricelist_product_id=rec.id)._compute_price()
21+
1122
@api.model
1223
def _get_tax_included_unit_price_from_price(
1324
self,

sale_ux/models/product_template.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ class ProductTemplate(models.Model):
2222
default=False,
2323
help="Indicates that this product is only used as packaging and does not use units.",
2424
)
25+
pricelist_ids = fields.One2many(
26+
"product.pricelist",
27+
compute="_compute_pricelist_ids",
28+
string="Pricelists",
29+
)
30+
31+
def _compute_pricelist_ids(self):
32+
for rec in self:
33+
rec.pricelist_ids = rec.pricelist_ids.search([("show_products", "=", True)])
34+
rec.pricelist_ids.with_context(pricelist_template_id=rec.id)._compute_price()
2535

2636
def _get_available_uoms(self):
2737
self.ensure_one()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
22
access_sale_order_global_discount_wizard,access_sale_order_global_discount_wizard,sale_ux.model_sale_order_global_discount_wizard,base.group_user,1,1,1,0
3+
access_product_pricelist_sale_user,product.pricelist.sale.user,product.model_product_pricelist,sales_team.group_sale_salesman,1,1,0,0
4+
access_product_pricelist_sale_user_all_leads,product.pricelist.sale.user.all.leads,product.model_product_pricelist,sales_team.group_sale_salesman_all_leads,1,1,0,0
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<odoo>
3+
<record id="product_pricelist_view" model="ir.ui.view">
4+
<field name="name">product.pricelist.form</field>
5+
<field name="model">product.pricelist</field>
6+
<field name="inherit_id" ref="product.product_pricelist_view"/>
7+
<field name="arch" type="xml">
8+
<field name="country_group_ids" position="before">
9+
<field name="show_products"/>
10+
</field>
11+
</field>
12+
</record>
13+
</odoo>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<odoo>
3+
<record id="product_template_only_form_view" model="ir.ui.view">
4+
<field name="name">product.template.prices.form</field>
5+
<field name="model">product.template</field>
6+
<field name="inherit_id" ref="product.product_template_form_view"/>
7+
<field name="arch" type="xml">
8+
<field name="pricelist_rule_ids" position="before">
9+
<field name="pricelist_ids" >
10+
<list delete='false' create='false' edit="false" editable="top" options="{'no_open': True}">
11+
<field name="name"/>
12+
<field name="price"/>
13+
<field name="currency_id" column_invisible="True"/>
14+
</list>
15+
</field>
16+
</field>
17+
<field name="pricelist_rule_ids" position="attributes">
18+
<attribute name="invisible">1</attribute>
19+
</field>
20+
</field>
21+
</record>
22+
</odoo>

0 commit comments

Comments
 (0)