Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 43 additions & 10 deletions tracking_manager/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from odoo import Command, api, models, tools
from odoo.exceptions import AccessError
from odoo.tools import float_compare, float_repr, float_round

from ..tools import format_m2m

Expand Down Expand Up @@ -61,21 +62,53 @@ def _tm_notify_owner(self, mode, changes=None):
def _tm_get_field_description(self, field_name):
return self._fields[field_name].get_description(self.env)["string"]

def _tm_get_digits(self, field):
"""Return the decimal digits of a float field, None for other fields.

Float fields declared without precision also return None: their values
are stored and compared with the full float precision.
"""
if field.type == "monetary":
currency_field = field.get_currency_field(self)
currency = currency_field and self[currency_field]
return currency.decimal_places if currency else None
if field.type != "float":
return None
digits = field.get_digits(self.env)
return digits and digits[1]

def _tm_has_changed(self, before, after, digits):
if digits is None:
return before != after
# `float_round`, applied to every written value, may return a value that
# differs by one unit in the last place from the one read from database
# (0.1 -> 0.09999999999999999). Both are stored identically, so such a
# difference is not a change.
return float_compare(before, after, precision_digits=digits) != 0

def _tm_format_values(self, field, before, after, digits):
if field.type == "many2many":
return format_m2m(before), format_m2m(after)
if field.type == "many2one":
return before.display_name, after["display_name"]
if digits is not None:
# displaying the raw value would expose the representation error of
# the rounding done on write (0.1 -> 0.09999999999999999)
return (
float_repr(float_round(before, precision_digits=digits), digits),
float_repr(float_round(after, precision_digits=digits), digits),
)
return before, after

def _tm_get_changes(self, values):
self.ensure_one()
changes = []
for field_name, before in values.items():
field = self._fields[field_name]
if before != self[field_name]:
if field.type == "many2many":
old = format_m2m(before)
new = format_m2m(self[field_name])
elif field.type == "many2one":
old = before.display_name
new = self[field_name]["display_name"]
else:
old = before
new = self[field_name]
after = self[field_name]
digits = self._tm_get_digits(field)
if self._tm_has_changed(before, after, digits):
old, new = self._tm_format_values(field, before, after, digits)
changes.append(
{
"name": self._tm_get_field_description(field_name),
Expand Down
1 change: 1 addition & 0 deletions tracking_manager/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Kévin Roche \<<kevin.roche@akretion.com>\>
- Sébastien BEAU \<<sebastien.beau@akretion.com>\>
- Maciej Wichowski \<<maciej@versada.eu>\> (https://versada.eu)
31 changes: 31 additions & 0 deletions tracking_manager/tests/test_tracking_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,23 @@ def messages(self):
self.flush_tracking()
return self.partner.message_ids

def _create_tracked_child(self, latitude):
"""Return a child partner whose (float) latitude is tracked."""
self.env.ref("base.field_res_partner__child_ids").custom_tracking = True
self.env.ref("base.field_res_partner__partner_latitude").custom_tracking = True
child = self.env["res.partner"].create(
{
"name": "Test child",
"parent_id": self.partner.id,
"partner_latitude": latitude,
}
)
self.flush_tracking()
self.partner.message_ids.unlink()
# values read from database are not rounded, unlike written ones
self.env.invalidate_all()
return child

def test_m2m_add_line(self):
self.partner = self.env["res.partner"].browse(self.partner.id)
self.partner.write(
Expand Down Expand Up @@ -271,3 +288,17 @@ def test_o2m_update_record(self):
)
child.write({"parent_id": False})
self.assertEqual(len(self.messages), 1)

def test_o2m_update_float_without_change(self):
child = self._create_tracked_child(0.1)
child.write({"partner_latitude": 0.1})
self.assertEqual(len(self.messages), 0)

def test_o2m_update_float(self):
child = self._create_tracked_child(0.1)
child.write({"partner_latitude": 1.5})
self.assertEqual(len(self.messages), 1)
self.assertEqual(self.messages.body.count("Change :"), 1)
# values are displayed with the precision of the field (10, 7)
self.assertIn("0.1000000", self.messages.body)
self.assertIn("1.5000000", self.messages.body)
Loading