Skip to content
Merged
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
15 changes: 14 additions & 1 deletion auditlog/models/rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self._transaction.tocompute = self._original_tocompute


class _Sentinel:
"""A falsy sentinel object as a placeholder for absent values."""

def __str__(self):
return ""

def __bool__(self):
return False


_SENTINEL = _Sentinel()


class AuditlogRule(models.Model):
_name = "auditlog.rule"
_description = "Auditlog - Rule"
Expand Down Expand Up @@ -506,7 +519,7 @@ def write_fast(self, vals, **kwargs):
# afterwards as it could not represent the real state
# of the data in the database
vals2 = dict(vals)
old_vals2 = dict.fromkeys(list(vals2.keys()), False)
old_vals2 = dict.fromkeys(list(vals2.keys()), _SENTINEL)
old_values = {id_: old_vals2 for id_ in self.ids}
new_values = {id_: vals2 for id_ in self.ids}
result = write_fast.origin(self, vals, **kwargs)
Expand Down
55 changes: 55 additions & 0 deletions auditlog/tests/test_auditlog.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,61 @@ def tearDown(self):
super(TestAuditlogFast, self).tearDown()


class TestAuditlogFastWriteEmptyValue(AuditLogRuleCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.test_model = cls.env["ir.model"].search([("model", "=", "res.partner")])
cls.auditlog_rule = cls.create_rule(
{
"name": "test.model_res_partner",
"model_id": cls.test_model.id,
"log_type": "fast",
"log_read": False,
"log_create": False,
"log_write": True,
"log_unlink": False,
}
)
cls.test_record = (
cls.env["res.partner"]
.with_context(tracking_disable=True)
.create(
{
"name": "testpartner3",
"phone": "123",
}
)
)
cls.auditlog_rule.subscribe()

def assert_has_one_log_line_with_empty_values(self):
logs = self.env["auditlog.log"].search(
[
("res_id", "=", self.test_record.id),
("model_id", "=", self.test_model.id),
]
)
self.assertEqual(len(logs), 1)
self.assertEqual(logs[0].model_name, "Contact")
self.assertEqual(logs[0].model_model, "res.partner")
log_lines = logs.mapped("line_ids")
self.assertEqual(len(log_lines), 1)
self.assertEqual(log_lines[0].field_name, "phone")
self.assertFalse(log_lines[0].old_value)
self.assertFalse(log_lines[0].old_value_text)
self.assertFalse(log_lines[0].new_value)
self.assertFalse(log_lines[0].new_value_text)

def test_when_removing_field_value_a_log_line_is_created(self):
self.test_record.write({"phone": False})
self.assert_has_one_log_line_with_empty_values()

def test_when_using_none_field_value_a_log_line_is_created(self):
self.test_record.write({"phone": None})
self.assert_has_one_log_line_with_empty_values()


class TestFieldRemoval(AuditLogRuleCommon):
@classmethod
def setUpClass(cls):
Expand Down