Friday, August 11, 2023
7 changes · master
Enhancements to existing features
This update harmonizes how hierarchy levels are applied in localized financial and tax reports across many countries. It helps reports display their sections more consistently, especially in localizations with non-standard report structures.
Original PR description
Added the improvements brought by https://github.com/odoo/enterprise/pull/43885 to localisations financial report when they don't follow the usual section distribution. task-3452382
Country and state names can now be translated for customer-facing experiences such as eCommerce checkout and PDF reports. This helps businesses operating in multilingual regions show place names in the customer's language, improving clarity and localization.
Original PR description
Country states are used in multiple customer facing flows, most notably eCommerce and pdf reports. Quite a few countries are multi-lingual and might have localized names for country states (e.g. Namur/Namen in Belgium, Nouveau-Brunswick/New-Brunswick in Canada, Fribourg/Freiburg/Friburgo/Friburg in Switwerland, etc.). This commit makes it possible to translate these names for better customer-facing experiences. Task-3285734
Odoo now supports clearer and more flexible search rules for records linked to other records, such as customers, projects, sales, and HR data. This improves consistency between different ways of filtering data and helps business rules return more reliable results.
Subtasks now automatically receive the same milestone as their parent task when appropriate, helping teams keep related work aligned. This reduces manual updates and makes project progress tracking more consistent.
Original PR description
As sub-tasks are a sub-set of a task that should logically be completed for the parent task to be completed, it would make sense for the sub-tasks to share the same milestone as their parent task by default. The milestone of a parent task is automatically set to its subtasks if: - The subtask has no milestone set - They belong to the same project or the subtask has no project set task-3450281
Financial reports for multiple country localizations now use a more consistent hierarchy and section structure. This makes localized balance sheets, profit and loss statements, and tax reports easier to read and compare across regions.
Original PR description
Added the improvements brought by https://github.com/odoo/enterprise/pull/43885 to localisations financial report when they don't follow the usual section distribution. task-3452382
Marketing Automation now tracks whether an activity has never been synced using a clear status field instead of relying on timing comparisons. This reduces edge-case synchronization errors when campaigns and activities are created or updated very close together.
Original PR description
Currently the marketing automation app distinguishes new marketing activities based on the `last_sync_date` (by comparing it to the creation date). This however, introduces some race conditions in…
Currently the marketing automation app distinguishes new marketing activities based on the `last_sync_date` (by comparing it to the creation date). This however, introduces some race conditions in certain edge cases. These edge cases occur because of two reasons: 1) The `create_date` is computed using the sql `now()` function which uses the transaction timestamp. When creating new activities after synchronizing a campaign in the same transaction, this can be problematic. 2) The `last_sync_date` is computed in python land, by the static `now()` method on the odoo `Datetime` field. This method truncates milliseconds. When creating activities and campaigns in the same transaction this yields nondeterministic behavior: the second hand of the clock might tick in between the creation of the campaign and the computation of `last_sync_date`. As a consequence it is better to be explicit about the state of the marketing activity. This commit introduces an extra field on the marketing activity model to do exactly this, allowing a proper forward port of the currently unmerged marketing automation fixes. This is needed as a separate commit, because the new field can no longer be introduced after the freeze for odoo version 16. opw-2643368
Subscription renewals now carry the freeze plan setting correctly based on whether a commission plan is assigned. This helps sales teams avoid incorrect commission behavior on renewed quotations and reduces manual corrections.
Original PR description
Description of the issue: Before this commit if freeze plan option is enabled in subscription but it remains disable during renewal of quotation IMP: After this commit freeze plan property value will true after renewal if commission_plan have some value and if commission_plan have no value then freeze plan property will becomes false after renewal even its value true. task-3397824
Original PR description
This PR aims to improve the correctness and expressivity of domains including conditions on relational fields. The proposed implementation allows a new syntax where conditions on relational fields…
This PR aims to improve the correctness and expressivity of domains including conditions on relational fields. The proposed implementation allows a new syntax where conditions on relational fields can be expressed in terms of a domain on the comodel using a subquery operator. Subquery operators include `any` and `all` (respectively expressing the condition that at least one or all related records must meet the conditions in the domain) and their logical inverses `not any` and `not all`. Some examples:
```python
# These can be expressed using the old syntax (using search)
[('x2many_ids', 'any', [('field', '=', value)])]
[('x2many_ids', 'not all', [('field', '=', value)])]
[('x2many_ids', 'any', ['|', ('active', '=', True), ('visible', '=', True)])]
# These could not previously be expressed (using search)
[('x2many_ids', 'all', [('field', '=', value)])]
[('x2many_ids', 'not any', [('field', '=', value)])]
[('x2many_ids', 'any', ['&', ('active', '=', True), ('visible', '=', True)])]
[('x2many_ids', 'all', ['|', ('active', '=', True), ('visible', '=', True)])]
```
The new implementation can be considered more correct because of the clearer semantics, but also because of a number of inconsistencies that existed between the `search` and `filtered_domain` implementations:
1) When using the logical not on a one2many or a many2many leaf. In general `filtered_domain` will adhere to commonly accepted logical not semantics (any record not matched by the original leaf will match the inverted one) while the orm `search` does not. This happens because the orm transforms inverted leafs by negating the operator inside the leaf. This does not generally work when multiple values can match the condition.
2) Using negative operators. A similar inconsistency is caused by the logic used by the `filtered_domain` method. Negative operators such as `!=` and `not in` are implemented by inverting the results of their positive counterparts (any record is matched by the `filtered_domain` method if it is not matched by the corresponding positive operator). Approximately, the positive operators can be used for matching any related record, while for the negative ones all related records have to meet the condition.
Additionally, when both these situations occur together for the same leaf, the inconsistency is lifted. However, semantically the results could still be considered wrong. Using the equals operator as an example, the current search semantics can be summarized as follows:
For the orm `search` method:
* `[('x2many_ids.field', '=', value)]` -> any =
* `[('x2many_ids.field', '!=', value)]` -> any !=
* `['!', ('x2many_ids.field', '=', value)]` -> any !=
* `['!', ('x2many_ids.field', '!=', value)]` -> any =
For the python side `filtered_domain` method:
* `[('x2many_ids.field', '=', value)]` -> any =
* `[('x2many_ids.field', '!=', value)]` -> all !=
* `['!', ('x2many_ids.field', '=', value)]` -> all !=
* `['!', ('x2many_ids.field', '!=', value)]` -> any =
Where any and all follow their traditional (python) semantics. Expressing the condition in terms of a nested field is necessary for the inconsistency to occur. These observations hold for fields `field` of any type: this means it also holds for cases where `field` is a relational field (note that `value` should not be `False` or `[]`, these cases are handled separately).
3) Note that, as a consequence of the above, there also exists a self-contradiction in the handling of x2many fields by the `search` method. This happens because the `search` method adheres to the same semantics as the `filtered_domain` method for conditions on non-nested fields. Again, for the `search` method, we get:
* `[('x2many_ids', '!=', value)]` -> all !=
* `[('x2many_ids.nested_x2many_ids', '!=', value)]` -> any !=
4) A less severe inconsistency occurs when specifying conditions on one2many or many2many fields that use a comodel domain as part of their definition. When using search this domain is ignored while it is taken into consideration when using `filtered_domain`.