Skip to content

Conversation

@StefanRijnhart
Copy link
Member

@StefanRijnhart StefanRijnhart commented Jan 2, 2026

Continued from #3391

@StefanRijnhart StefanRijnhart force-pushed the 19.0-mig-auditlog branch 6 times, most recently from 32d9e39 to 3b60fc5 Compare January 2, 2026 20:17
@StefanRijnhart StefanRijnhart changed the title [19.0][MIG] auditlog; Migration to 19.0 [19.0][MIG] auditlog: Migration to 19.0 Jan 2, 2026
@StefanRijnhart StefanRijnhart force-pushed the 19.0-mig-auditlog branch 2 times, most recently from 16d7007 to 292d89c Compare January 2, 2026 21:06
@StefanRijnhart
Copy link
Member Author

/ocabot migration auditlog

@OCA-git-bot OCA-git-bot added this to the 19.0 milestone Jan 2, 2026
@OCA-git-bot OCA-git-bot mentioned this pull request Jan 2, 2026
40 tasks
@StefanRijnhart
Copy link
Member Author

test_auditlog for 19.0 is green at #3484

@StefanRijnhart StefanRijnhart force-pushed the 19.0-mig-auditlog branch 8 times, most recently from 065c19e to 8b2af87 Compare January 3, 2026 22:58
self._transaction.protected = StackMap["Field", OrderedSet["IdType"]]()
self._transaction.tocompute = defaultdict["Field", OrderedSet["IdType"]](
OrderedSet
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest using something like

def copy_empty_defaultdict(_dict):
    return type(_dict)(_dict.default_factory)

for all defaultdicts here. This way we don't run into subtle errors if the default factory changes in core, or type hints actually do something and change

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I've taken a more naive approach using copy + clear: https://github.com/OCA/server-tools/compare/8b2af873bdee80d05eb3d1b10e68cd1dedf65644..8976baea64f9d1528da855809e2e6a3e4b19363f. It seems to work for the StackMap instance as well. Do you agree with this implementation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(rebased to fix codecov's project coverage relative to the last build of the target branch, which had progressed in the mean time).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, the shallow copy looks innocent enough. do we have any measurements how expensive this is?

lembregtse and others added 29 commits January 11, 2026 17:27
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/
Currently translated at 97.7% (85 of 87 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/tr/
[IMP] auditlog: Add name to action for UX
Currently translated at 100.0% (91 of 91 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/it/
Currently translated at 95.6% (87 of 91 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/tr/
Though TransactionCase rolls back database changes, it does not
call `unlink` on `auditlog.rule` records, meaning that `unsubscribe`
is never called to unpatch model methods. This causes subsequent
tests in other modules to unexpectedly execute patched methods.

This commit adds the `AuditLogRuleCommon` test class in an
attempt to identify and prevent patched methods from contaminating
the test environment.
Steps to Reproduce:

Install auditlog and purchase_tier_validation. Create an auditlog rule on
the Tier Exception model. Create a new tier exception record for the purchase
order model without any fields. In an export, check the value for the stored
computed field `model_name`.

Desired outcome:

The value for `model_name` is 'purchase.order'.

Actual outcome:

There is no value for the stored computed field `model_name`. When trying to
edit the `Fields` model, which depends on a valid value for this field, an error
occurs saying 'Compute method failed to assign
tier.validation.exception(1,).valid_model_field_ids'.

Analysis:

When `read` is executed under the scope of the new `ThrowAwayCache` decorator
(OCA#3374), recomputes may be performed and dequeued from
`self.env.cache.transaction.tocompute`. To make sure the recomputed values still
end up in the non-volatile as well, we need to preserve the tocompute attribute
from the original transaction.
Currently translated at 96.7% (88 of 91 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/ja/
Currently translated at 100.0% (91 of 91 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/it/
Currently translated at 95.6% (87 of 91 strings)

Translation: server-tools-18.0/server-tools-18.0-auditlog
Translate-URL: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-auditlog/sv/
Fixes OCA#3424

Previous approach was to create a copy, so that the recomputes were also applied
to the real world cache. However, this causes an issue when a field is required
that is only available in the real world cache, such as the `date` field in

```
    @api.depends('date', 'sequence')
    def _compute_internal_index(self):
        for st_line in self.filtered(lambda line: line._origin.id):
            st_line.internal_index = f'{st_line.date.strftime("%Y%m%d")}'
            ...
```

It actually makes sense to avoid recomputes in this isolated environment that
is meant to retrieve the original values from before the write.

Fixes
```
  File "/odoo/odoo/addons/account/models/account_bank_statement_line.py", line 427, in create
    st_line.move_id.write(to_write)
  File "/odoo/server-tools/auditlog/models/rule.py", line 464, in write_full
    old_values = {d["id"]: d for d in records_write.read(fields_list)}
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/server-tools/auditlog/models/rule.py", line 406, in read
    result = read.origin(self, fields, load, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/odoo/odoo/models.py", line 3857, in read
    self._origin.fetch(fields)
  File "/odoo/odoo/odoo/models.py", line 4153, in fetch
    fetched = self._fetch_query(query, fields_to_fetch)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/odoo/odoo/models.py", line 4264, in _fetch_query
    field.read(fetched)
  File "/odoo/odoo/odoo/fields.py", line 4654, in read
    lines = comodel.search_fetch(domain, field_names)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/odoo/odoo/models.py", line 1781, in search_fetch
    return self._fetch_query(query, fields_to_fetch)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/odoo/odoo/models.py", line 4240, in _fetch_query
    rows = self.env.execute_query(query.select(*sql_terms))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/odoo/odoo/odoo/api.py", line 992, in execute_query
    self.flush_query(query)
  File "/odoo/odoo/odoo/api.py", line 984, in flush_query
    self[model_name].flush_model(field_names)
  File "/odoo/odoo/odoo/models.py", line 6768, in flush_model
    self._recompute_model(fnames)
  File "/odoo/odoo/odoo/models.py", line 7332, in _recompute_model
    self._recompute_field(field)
  File "/odoo/odoo/odoo/models.py", line 7360, in _recompute_field
    field.recompute(records)
  File "/odoo/odoo/odoo/fields.py", line 1471, in recompute
    apply_except_missing(self.compute_value, recs)
  File "/odoo/odoo/odoo/fields.py", line 1444, in apply_except_missing
    func(records)
  File "/odoo/odoo/odoo/fields.py", line 1493, in compute_value
    records._compute_field_value(self)
  File "/odoo/odoo/odoo/models.py", line 5297, in _compute_field_value
    fields.determine(field.compute, self)
  File "/odoo/odoo/odoo/fields.py", line 110, in determine
    return needle(*args)
           ^^^^^^^^^^^^^
  File "/odoo/odoo/addons/account/models/account_bank_statement_line.py", line 295, in _compute_internal_index
    st_line.internal_index = f'{st_line.date.strftime("%Y%m%d")}' \
                                ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'strftime'
```
Co-authored-by: Eric Lembregts <[email protected]>
Co-authored-by: Raf Ven <[email protected]>
The concept of subscriptions is slightly misleading in the auditlog domain
because users do not 'subscribe' to individual rules and no notifications
are being sent out.
Since odoo/odoo@6dc96811c24ec, test methods from
inherited test classes are not run by default.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.