Skip to content

Commit 8103f76

Browse files
vvrossemyankinmax
authored andcommitted
[ADD] res_partner_product_pricelist_operating_unit
1 parent b309481 commit 8103f76

15 files changed

Lines changed: 725 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
========================================
2+
Partner Product Pricelist Operating Unit
3+
========================================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:78fb292c8f1e1718ad7edc8d1f1199839efe327922a48f467289551d4ab071b9
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Foperating--unit-lightgray.png?logo=github
20+
:target: https://github.com/OCA/operating-unit/tree/17.0/res_partner_product_pricelist_operating_unit
21+
:alt: OCA/operating-unit
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/operating-unit-17-0/operating-unit-17-0-res_partner_product_pricelist_operating_unit
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/operating-unit&target_branch=17.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module introduces the following features:
32+
33+
- Ensures that the Product Pricelist assigned to a Partner belongs to
34+
one of the Partner's Operating Units (OUs).
35+
- Adds a constraint to prevent assigning a Pricelist from an
36+
unauthorized Operating Unit.
37+
- Filters the Pricelists in the Partner form based on the Partner's
38+
Operating Units.
39+
40+
**Table of contents**
41+
42+
.. contents::
43+
:local:
44+
45+
Usage
46+
=====
47+
48+
- Add a Pricelist to the Customer
49+
50+
Bug Tracker
51+
===========
52+
53+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/operating-unit/issues>`_.
54+
In case of trouble, please check there if your issue has already been reported.
55+
If you spotted it first, help us to smash it by providing a detailed and welcomed
56+
`feedback <https://github.com/OCA/operating-unit/issues/new?body=module:%20res_partner_product_pricelist_operating_unit%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
57+
58+
Do not contact contributors directly about support or help with technical issues.
59+
60+
Credits
61+
=======
62+
63+
Authors
64+
-------
65+
66+
* Camptocamp
67+
68+
Contributors
69+
------------
70+
71+
- Vincent Van Rossem <vincent.vanrossem@camptocamp.com>
72+
73+
Maintainers
74+
-----------
75+
76+
This module is maintained by the OCA.
77+
78+
.. image:: https://odoo-community.org/logo.png
79+
:alt: Odoo Community Association
80+
:target: https://odoo-community.org
81+
82+
OCA, or the Odoo Community Association, is a nonprofit organization whose
83+
mission is to support the collaborative development of Odoo features and
84+
promote its widespread use.
85+
86+
This module is part of the `OCA/operating-unit <https://github.com/OCA/operating-unit/tree/17.0/res_partner_product_pricelist_operating_unit>`_ project on GitHub.
87+
88+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2025 Camptocamp
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
{
4+
"name": "Partner Product Pricelist Operating Unit",
5+
"version": "17.0.1.0.0",
6+
"author": "Camptocamp, Odoo Community Association (OCA)",
7+
"license": "AGPL-3",
8+
"website": "https://github.com/OCA/operating-unit",
9+
"category": "Product",
10+
"depends": [
11+
# OCA/operating-unit
12+
"product_pricelist_operating_unit",
13+
"res_partner_operating_unit",
14+
],
15+
"data": [
16+
"views/res_partner.xml",
17+
],
18+
"installable": True,
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import product_pricelist
2+
from . import res_partner
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# 2025 Camptocamp SA (https://www.camptocamp.com).
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
3+
from odoo import api, models
4+
5+
6+
class ProductPricelist(models.Model):
7+
_inherit = "product.pricelist"
8+
9+
@api.model
10+
def _get_partner_pricelist_multi(self, partner_ids):
11+
res = super()._get_partner_pricelist_multi(partner_ids)
12+
partners = self.env["res.partner"].browse(partner_ids).exists()
13+
partners_by_id = {partner.id: partner for partner in partners}
14+
15+
for partner_id in res:
16+
partner = partners_by_id.get(partner_id)
17+
if not partner or not partner.operating_unit_ids:
18+
res[partner_id] = False
19+
continue
20+
21+
pricelist_operating_unit = res[partner_id].operating_unit_id
22+
if (
23+
pricelist_operating_unit
24+
and pricelist_operating_unit not in partner.operating_unit_ids
25+
):
26+
domain = self._get_product_pricelist_operating_unit_domain(partner)
27+
res[partner_id] = self.search(domain, limit=1) or False
28+
29+
return res
30+
31+
def _get_product_pricelist_operating_unit_domain(self, partner):
32+
domain = [
33+
("operating_unit_id", "in", partner.operating_unit_ids.ids),
34+
("company_id", "in", [self.env.company.id, False]),
35+
("active", "=", True),
36+
]
37+
return domain
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# 2025 Camptocamp SA (https://www.camptocamp.com).
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
3+
from odoo import _, api, models
4+
from odoo.exceptions import ValidationError
5+
6+
7+
class ResPartner(models.Model):
8+
_inherit = "res.partner"
9+
10+
@api.depends("operating_unit_ids")
11+
def _compute_product_pricelist(self):
12+
return super()._compute_product_pricelist()
13+
14+
@api.constrains("operating_unit_ids", "property_product_pricelist")
15+
def _check_pricelist_operating_unit(self):
16+
for partner in self:
17+
pricelist = partner.property_product_pricelist
18+
if (
19+
pricelist
20+
and pricelist.operating_unit_id
21+
and pricelist.operating_unit_id not in partner.operating_unit_ids
22+
):
23+
raise ValidationError(
24+
_(
25+
"Pricelist '%(pricelist)s' belongs to "
26+
"Operating Unit '%(operating_unit)s' "
27+
"which is not associated to this partner.",
28+
pricelist=pricelist.name,
29+
operating_unit=pricelist.operating_unit_id.name,
30+
)
31+
)
32+
33+
def _commercial_fields(self):
34+
# list of fields that are managed by the commercial entity
35+
# to which a partner belongs.
36+
return super()._commercial_fields() + ["operating_unit_ids"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build-system]
2+
requires = ["whool"]
3+
build-backend = "whool.buildapi"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Vincent Van Rossem \<<vincent.vanrossem@camptocamp.com>\>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This module introduces the following features:
2+
3+
- Ensures that the Product Pricelist assigned to a Partner belongs to one of the Partner's Operating Units (OUs).
4+
- Adds a constraint to prevent assigning a Pricelist from an unauthorized Operating Unit.
5+
- Filters the Pricelists in the Partner form based on the Partner's Operating Units.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Add a Pricelist to the Customer

0 commit comments

Comments
 (0)