Skip to content

Commit 0ce7836

Browse files
[IMP] product_secondary_unit: add configuration for report presentation
Co-authored-by: Yoshi Tashiro <tashiro@quartile.co>
1 parent 812783c commit 0ce7836

File tree

11 files changed

+381
-33
lines changed

11 files changed

+381
-33
lines changed

product_secondary_unit/README.rst

Lines changed: 51 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,48 @@ other units with their conversion factor.
4036
.. contents::
4137
:local:
4238

39+
Configuration
40+
=============
41+
42+
To configure this module, go to **Settings** and locate the **Units of
43+
Measure** section.
44+
45+
Secondary Unit Price Display
46+
----------------------------
47+
48+
Configure how unit prices and quantities are shown in reports when
49+
secondary units are used.
50+
51+
- **Sales**: Select the display policy for sales order and customer
52+
invoice reports and portal views.
53+
- **Purchase**: Select the display policy for purchase order and vendor
54+
bill reports and portal views.
55+
56+
Available options:
57+
58+
- **Primary Unit Price Only**: Show only the primary unit price.
59+
- **Prioritize Secondary Unit Price**: Show the secondary unit price
60+
when available, otherwise fall back to the primary unit price.
61+
- **Both Primary and Secondary Unit Prices**: Show both primary and
62+
secondary unit prices.
63+
64+
Hide Secondary Qty Column
65+
-------------------------
66+
67+
Hide the separate **Second Qty** column in reports.
68+
69+
- When enabled, the **Second Qty** column is hidden in reports. The
70+
secondary quantity can still be shown in the main **Qty** column
71+
depending on the selected price display policy above.
72+
- Apply the setting per document type:
73+
74+
- **Sales**
75+
- **Purchase**
76+
77+
These settings are intended to be used by dependency modules (for
78+
example, ``purchase_order_secondary_unit`` and
79+
``account_move_secondary_unit``).
80+
4381
Usage
4482
=====
4583

@@ -70,11 +108,14 @@ Authors
70108
Contributors
71109
------------
72110

73-
- Carlos Dauden <carlos.dauden@tecnativa.com>
74-
- Sergio Teruel <sergio.teruel@tecnativa.com>
75-
- Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
76-
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
77-
- Alan Ramos <alan.ramos@jarsa.com.mx>
111+
- Carlos Dauden <carlos.dauden@tecnativa.com>
112+
- Sergio Teruel <sergio.teruel@tecnativa.com>
113+
- Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
114+
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
115+
- Alan Ramos <alan.ramos@jarsa.com.mx>
116+
- `Quartile <https://www.quartile.co>`__:
117+
118+
- Aung Ko Ko Lin
78119

79120
Maintainers
80121
-----------

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: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
required=True,
21+
)
22+
secondary_uom_price_display_purchase = fields.Selection(
23+
selection=PRICE_DISPLAY_SELECTION,
24+
string="Secondary Unit Price Display (Purchase)",
25+
default="primary",
26+
required=True,
27+
)
28+
# Added for supporting the existing report presentation. We can drop this together
29+
# with the second qty column in reports if the community agrees with it.
30+
hide_secondary_uom_column_sale = fields.Boolean(
31+
string="Hide Secondary UoM Column (Sales)",
32+
default=False,
33+
)
34+
hide_secondary_uom_column_purchase = fields.Boolean(
35+
string="Hide Secondary UoM Column (Purchase)",
36+
default=False,
37+
)
38+
39+
def hide_secondary_uom_column(self, record):
40+
"""Return whether to hide the 'Second Qty' column for this document type."""
41+
if record._name == "sale.order" or (
42+
record._name == "account.move"
43+
and record.is_sale_document(include_receipts=True)
44+
):
45+
return self.hide_secondary_uom_column_sale
46+
if record._name == "purchase.order" or (
47+
record._name == "account.move"
48+
and record.is_purchase_document(include_receipts=True)
49+
):
50+
return self.hide_secondary_uom_column_purchase
51+
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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
To configure this module, go to **Settings** and locate the **Units of Measure**
2+
section.
3+
4+
## Secondary Unit Price Display
5+
6+
Configure how unit prices and quantities are shown in reports when secondary units are
7+
used.
8+
9+
- **Sales**: Select the display policy for sales order and customer invoice reports and
10+
portal views.
11+
- **Purchase**: Select the display policy for purchase order and vendor bill reports and
12+
portal views.
13+
14+
Available options:
15+
16+
- **Primary Unit Price Only**: Show only the primary unit price.
17+
- **Prioritize Secondary Unit Price**: Show the secondary unit price when available,
18+
otherwise fall back to the primary unit price.
19+
- **Both Primary and Secondary Unit Prices**: Show both primary and secondary unit
20+
prices.
21+
22+
## Hide Secondary Qty Column
23+
24+
Hide the separate **Second Qty** column in reports.
25+
26+
- When enabled, the **Second Qty** column is hidden in reports. The secondary quantity
27+
can still be shown in the main **Qty** column depending on the selected price display
28+
policy above.
29+
- Apply the setting per document type:
30+
- **Sales**
31+
- **Purchase**
32+
33+
These settings are intended to be used by dependency modules (for example,
34+
`purchase_order_secondary_unit` and `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 \<<kittiu@ecosoft.co.th>\>
44
- Pimolnat Suntian \<<pimolnats@ecosoft.co.th>\>
55
- Alan Ramos \<<alan.ramos@jarsa.com.mx>\>
6+
- [Quartile](https://www.quartile.co):
7+
- Aung Ko Ko Lin

0 commit comments

Comments
 (0)