Skip to content

Commit c8dcb39

Browse files
[IMP] product_secondary_unit: add configuration for report presentation
Co-authored-by: Yoshi Tashiro <[email protected]>
1 parent 812783c commit c8dcb39

File tree

11 files changed

+365
-33
lines changed

11 files changed

+365
-33
lines changed

product_secondary_unit/README.rst

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
.. image:: https://odoo-community.org/readme-banner-image
2-
:target: https://odoo-community.org/get-involved?utm_source=readme
3-
:alt: Odoo Community Association
4-
51
======================
62
Product Secondary Unit
73
======================
@@ -17,7 +13,7 @@ Product Secondary Unit
1713
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
1814
:target: https://odoo-community.org/page/development-status
1915
:alt: Production/Stable
20-
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
2117
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
2218
:alt: License: AGPL-3
2319
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github
@@ -40,6 +36,43 @@ other units with their conversion factor.
4036
.. contents::
4137
:local:
4238

39+
Configuration
40+
=============
41+
42+
To configure this module, go to *Settings* and look for the Units of
43+
Measure section:
44+
45+
- **Secondary Unit Price Display (Purchase)**: Controls how unit prices
46+
are shown in purchase order and vendor bill reports and portal views
47+
when secondary units are used.
48+
49+
- *Primary Unit Price Only*: Shows only the primary unit price
50+
- *Prioritize Secondary Unit Price*: Shows secondary unit price when
51+
available, falls back to primary otherwise
52+
- *Both Primary and Secondary Unit Prices*: Shows both prices
53+
54+
- **Hide Secondary UoM Column (Purchase)**: When enabled, hides the
55+
separate Secondary Qty column in purchase order and vendor bill
56+
reports and portal views. The secondary quantity will still be shown
57+
in the main Qty column based on the price display setting above.
58+
59+
- **Secondary Unit Price Display (Sales)**: Controls how unit prices
60+
are shown in sales order and customer invoice reports and portal
61+
views when secondary units are used.
62+
63+
- *Primary Unit Price Only*: Shows only the primary unit price
64+
- *Prioritize Secondary Unit Price*: Shows secondary unit price when
65+
available, falls back to primary otherwise
66+
- *Both Primary and Secondary Unit Prices*: Shows both prices
67+
68+
- **Hide Secondary UoM Column (Sales)**: When enabled, hides the
69+
separate Secondary Qty column in sales order and customer invoice
70+
reports and portal views. The secondary quantity will still be shown
71+
in the main Qty column based on the price display setting above.
72+
73+
These settings are intended to be used by dependency modules (e.g.,
74+
purchase_order_secondary_unit, account_move_secondary_unit).
75+
4376
Usage
4477
=====
4578

@@ -70,11 +103,14 @@ Authors
70103
Contributors
71104
------------
72105

73-
- Carlos Dauden <[email protected]>
74-
- Sergio Teruel <[email protected]>
75-
- Kitti Upariphutthiphong <[email protected]>
76-
- Pimolnat Suntian <[email protected]>
77-
- Alan Ramos <[email protected]>
106+
- Carlos Dauden <[email protected]>
107+
- Sergio Teruel <[email protected]>
108+
- Kitti Upariphutthiphong <[email protected]>
109+
- Pimolnat Suntian <[email protected]>
110+
- Alan Ramos <[email protected]>
111+
- `Quartile <https://www.quartile.co>`__:
112+
113+
- Aung Ko Ko Lin
78114

79115
Maintainers
80116
-----------

product_secondary_unit/__manifest__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
"application": False,
1313
"installable": True,
1414
"depends": ["product"],
15-
"data": ["security/ir.model.access.csv", "views/product_views.xml"],
15+
"data": [
16+
"security/ir.model.access.csv",
17+
"views/product_views.xml",
18+
"views/res_config_settings_views.xml",
19+
],
1620
"maintainers": ["sergio-teruel"],
1721
}

product_secondary_unit/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
from . import product_second_unit
44
from . import product_secondary_unit_mixin
55
from . import product_template
6+
from . import res_company
7+
from . import res_config_settings

product_secondary_unit/models/product_secondary_unit_mixin.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,54 @@ def default_get(self, fields_list):
147147
):
148148
defaults["secondary_uom_qty"] = 1.0
149149
return defaults
150+
151+
def _get_secondary_uom_report_type(self):
152+
"""Return 'sale', 'purchase', or None."""
153+
self.ensure_one()
154+
if self._name == "sale.order.line" or (
155+
self._name == "account.move.line"
156+
and self.move_id.is_sale_document(include_receipts=True)
157+
):
158+
return "sale"
159+
if self._name == "purchase.order.line" or (
160+
self._name == "account.move.line" and self.move_id.is_purchase_document()
161+
):
162+
return "purchase"
163+
return None
164+
165+
def _get_secondary_uom_report_settings(self):
166+
"""Return (display_mode, hide_secondary_col)."""
167+
self.ensure_one()
168+
if not self.secondary_uom_id:
169+
return ("primary", True)
170+
report_type = self._get_secondary_uom_report_type()
171+
if not report_type:
172+
return ("primary", True)
173+
company = self.company_id
174+
if report_type == "purchase":
175+
return (
176+
company.secondary_uom_price_display_purchase,
177+
company.hide_secondary_uom_column_purchase,
178+
)
179+
return (
180+
company.secondary_uom_price_display_sale,
181+
company.hide_secondary_uom_column_sale,
182+
)
183+
184+
def get_secondary_uom_display_mode(self):
185+
"""Return the secondary UoM price display mode for QWeb reports."""
186+
self.ensure_one()
187+
return self._get_secondary_uom_report_settings()[0]
188+
189+
def report_show_price_uom(self, uom_source=None):
190+
"""Return True if UoM should be shown in price column.
191+
192+
UoM is shown when the line displays multiple UoMs.
193+
"""
194+
self.ensure_one()
195+
if not self.secondary_uom_id:
196+
return False
197+
display, hide_col = self._get_secondary_uom_report_settings()
198+
if uom_source == "primary_uom" and display == "secondary":
199+
return False
200+
return not hide_col or display == "both"

product_secondary_unit/models/product_template.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,33 @@ def _get_default_secondary_uom(self):
2121
and self.secondary_uom_ids[0]
2222
or self.secondary_uom_ids
2323
)
24+
25+
def _compute_template_secondary_uom_field(self, fname):
26+
"""Helper to sync template secondary UoM field from variant.
27+
Can be used in modules depending on product_secondary_unit to implement
28+
compute methods for secondary UoM fields on product.template.
29+
- Single variant: Sync the variant's value to the template
30+
- Multiple variants: Keep the existing template value
31+
:param str fname: name of the secondary UoM field to compute
32+
"""
33+
for template in self:
34+
if len(template.product_variant_ids) == 1:
35+
template[fname] = template.product_variant_ids[fname]
36+
# Keep existing value when multiple variants (don't clear)
37+
38+
def _inverse_template_secondary_uom_field(self, fname):
39+
"""Helper to propagate template secondary UoM field to variants.
40+
Can be used in modules depending on product_secondary_unit to implement
41+
inverse methods for secondary UoM fields on product.template.
42+
- Single variant: Always sync the template's value to the variant
43+
- Multiple variants: Only update variants without their own setting
44+
:param str fname: name of the secondary UoM field to propagate
45+
"""
46+
for template in self:
47+
if len(template.product_variant_ids) == 1:
48+
variants_to_update = template.product_variant_ids
49+
else:
50+
variants_to_update = template.product_variant_ids.filtered(
51+
lambda v, f=fname: not v[f]
52+
)
53+
variants_to_update[fname] = template[fname]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2026 Quartile (https://www.quartile.co)
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import fields, models
5+
6+
PRICE_DISPLAY_SELECTION = [
7+
("primary", "Primary Unit Price Only"),
8+
("secondary", "Prioritize Secondary Unit Price"),
9+
("both", "Both Primary and Secondary Unit Prices"),
10+
]
11+
12+
13+
class ResCompany(models.Model):
14+
_inherit = "res.company"
15+
16+
secondary_uom_price_display_sale = fields.Selection(
17+
selection=PRICE_DISPLAY_SELECTION,
18+
string="Secondary Unit Price Display (Sales)",
19+
default="primary",
20+
)
21+
secondary_uom_price_display_purchase = fields.Selection(
22+
selection=PRICE_DISPLAY_SELECTION,
23+
string="Secondary Unit Price Display (Purchase)",
24+
default="primary",
25+
)
26+
# Added for supporting the existing report presentation. We can drop this together
27+
# with the second qty column in reports if the community agrees with it.
28+
hide_secondary_uom_column_sale = fields.Boolean(
29+
string="Hide Secondary UoM Column (Sales)",
30+
default=False,
31+
)
32+
hide_secondary_uom_column_purchase = fields.Boolean(
33+
string="Hide Secondary UoM Column (Purchase)",
34+
default=False,
35+
)
36+
37+
def hide_secondary_uom_column(self, record):
38+
"""Return whether to hide the 'Second Qty' column for this document type."""
39+
if record._name == "sale.order" or (
40+
record._name == "account.move"
41+
and record.is_sale_document(include_receipts=True)
42+
):
43+
return self.hide_secondary_uom_column_sale
44+
if record._name == "purchase.order" or (
45+
record._name == "account.move"
46+
and record.is_purchase_document(include_receipts=True)
47+
):
48+
return self.hide_secondary_uom_column_purchase
49+
return True
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2026 Quartile (https://www.quartile.co)
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import fields, models
5+
6+
7+
class ResConfigSettings(models.TransientModel):
8+
_inherit = "res.config.settings"
9+
10+
secondary_uom_price_display_sale = fields.Selection(
11+
related="company_id.secondary_uom_price_display_sale",
12+
readonly=False,
13+
)
14+
secondary_uom_price_display_purchase = fields.Selection(
15+
related="company_id.secondary_uom_price_display_purchase",
16+
readonly=False,
17+
)
18+
hide_secondary_uom_column_sale = fields.Boolean(
19+
related="company_id.hide_secondary_uom_column_sale",
20+
readonly=False,
21+
)
22+
hide_secondary_uom_column_purchase = fields.Boolean(
23+
related="company_id.hide_secondary_uom_column_purchase",
24+
readonly=False,
25+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
To configure this module, go to *Settings* and look for the Units of Measure
2+
section:
3+
4+
- **Secondary Unit Price Display (Purchase)**: Controls how unit prices are shown in
5+
purchase order and vendor bill reports and portal views when secondary units are used.
6+
- *Primary Unit Price Only*: Shows only the primary unit price
7+
- *Prioritize Secondary Unit Price*: Shows secondary unit price when available, falls
8+
back to primary otherwise
9+
- *Both Primary and Secondary Unit Prices*: Shows both prices
10+
11+
- **Hide Secondary UoM Column (Purchase)**: When enabled, hides the separate Secondary Qty column
12+
in purchase order and vendor bill reports and portal views. The secondary quantity will still be
13+
shown in the main Qty column based on the price display setting above.
14+
15+
- **Secondary Unit Price Display (Sales)**: Controls how unit prices are shown in
16+
sales order and customer invoice reports and portal views when secondary units are used.
17+
- *Primary Unit Price Only*: Shows only the primary unit price
18+
- *Prioritize Secondary Unit Price*: Shows secondary unit price when available, falls
19+
back to primary otherwise
20+
- *Both Primary and Secondary Unit Prices*: Shows both prices
21+
22+
- **Hide Secondary UoM Column (Sales)**: When enabled, hides the separate Secondary Qty column
23+
in sales order and customer invoice reports and portal views. The secondary quantity will still be
24+
shown in the main Qty column based on the price display setting above.
25+
26+
These settings are intended to be used by dependency modules (e.g.,
27+
purchase_order_secondary_unit, account_move_secondary_unit).

product_secondary_unit/readme/CONTRIBUTORS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
- Kitti Upariphutthiphong \<<[email protected]>\>
44
- Pimolnat Suntian \<<[email protected]>\>
55
- Alan Ramos \<<[email protected]>\>
6+
- [Quartile](https://www.quartile.co):
7+
- Aung Ko Ko Lin

0 commit comments

Comments
 (0)