Thursday, July 9, 2026
7 changes · 19.0
Enhancements to existing features
Odoo can now use official daily exchange rates from the Central Bank of Azerbaijan for automatic currency updates. This helps businesses using AZN translate multi-currency accounting and tax transactions more accurately, including rates quoted for larger nominal amounts.
Original PR description
This commit adds the Central Bank of Azerbaijan (CBA) as a supported service provider for automatic currency rate updates. Purpose: To ensure multi-currency accounting entries and taxable transactions are accurately translated into the national currency (AZN) using the official exchange rate defined by the CBA for the transaction day. Functionality: -Enables fetching official daily exchange rates directly from CBA via XML. -Automatically handles rates defined for different nominal quantities (e.g., rates quoted per 100 units instead of 1 unit). Backport of: https://github.com/odoo/enterprise/pull/122626 task-6112867
Resolved issues and error corrections
The project Gantt view now correctly shades unavailable periods when a user has employees in multiple companies. This keeps visual scheduling cues aligned with time-off warnings, helping planners avoid assigning work during approved absences.
Original PR description
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and…
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and create a task during the approved time-off period the warning is shown and the Gantt cell is grayed out. - Select both companies and create a task during the same time-off period in Tasks > Gantt. Issue: When multiple companies are selected, the time-off warning is still displayed but the corresponding Gantt cells are no longer grayed out, leading to an inconsistency between the warning logic and the Gantt rendering. Cause: In multi-company setups, a user can be linked to multiple resources. The Gantt unavailability logic assumed a one-to-one relationship between user and resource causing unavailability intervals from some resources to be overwritten. Solution: Aggregate unavailability intervals from all resources linked to the same user, limited to the selected companies, and merge them with the company calendar unavailability to ensure consistent Gantt gray rendering. Related PR: https://github.com/odoo/enterprise/pull/57028 task-5089385 Forward-Port-Of: odoo/enterprise#105288
This fix prevents an error when users propose adding a step from the Shop Floor for manufacturing orders whose bill of materials contains very similar operations. It makes the improvement suggestion flow more reliable for teams using PLM to update manufacturing instructions.
Original PR description
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback…
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback when proposing an improvement from the Shop Floor. **Steps to reproduce** - Install the Product Lifecycle Management app. - Create a BOM for any product with two operations that: - Have the same name and work center - Have no variant - Create and confirm a Manufacturing Order for that product. - Open the Shop Floor view. - Click the gear icon -> Update Instructions -> Improvement Suggestion -> Add a Step -> Propose a Change. -> A traceback occurs **Cause** When adding a step: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L10 It tries to find the corresponding operation in the ECO's new BoM. This relies on `_get_sync_values()`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_plm/models/mrp_routing.py#L9-L13 Because two operations share the same name, work center, and no variant, both match the filter: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L39 This results in a singleton error when accessing `operation.id`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L42 opw-6241880 Forward-Port-Of: odoo/enterprise#119404
Imported Chilean electronic invoices now use the amount in the invoice currency instead of incorrectly applying Chilean peso amounts. This prevents vendor bills in currencies such as UF from being created with wrong totals, reducing accounting corrections and reconciliation issues.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Duplicating certain Sign templates could fail when the same signer roles appeared across multiple documents and fields. The fix prevents already-processed signer roles from being copied again, allowing affected templates to duplicate successfully.
Original PR description
Issue: This [loop](https://github.com/odoo-dev/enterprise/blob/55bb2cc570451361701d53583f019ed832a5e5d3/sign/models/sign_item.py#L59-L63) runs multiple times with the same approvers(sign.item.role), but doesn't take into account the already 'seen map' inside the base copy function for batching. If they are already seen they will return a non-iterable [None]. To replicate: 1) Sign -> Template -> upload PDF 2) Go into the template 3) Add 2 Documents, with 2 signers and multiple fields on both documents 4) Save -> gear Icon -> make into template 5) Go back to the list view of templates 6) Select the template -> Gear Icon -> Duplicate Fix: add an already seen check to skip if already seen. opw-6352408
Kenyan POS refunds can now be validated without triggering an error during eTIMS processing. The fix also improves handling when multiple offline orders are synchronized together, helping keep sales and refund workflows running smoothly.
Original PR description
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised…
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised when validating the refund: `ValueError: Expected singleton: pos.order(<refund>, <original>)` raised in `get_l10n_ke_edi_oscu_pos_data`. Cause: - When syncing a refund, `sync_from_ui` returns both the new refund order and the original refunded order. `waitForPushOrder` forces post-processing for every Kenyan order in that list, so `beforePostPushOrderResolve` receives both ids in `order_server_ids` and forwards them as-is to `action_post_order` and `get_l10n_ke_edi_oscu_pos_data`, both of which expect a single record. `action_post_order` fails the same way, but its error was silently swallowed by the surrounding try/catch, letting the traceback surface only on the second call. - The same multi-id list is also produced whenever several orders created offline get synced together once back online. Solution: - `get_l10n_ke_edi_oscu_pos_data` is only needed for the receipt of the order being validated, so call it with `order.id` instead of the full `order_server_ids` list. - Replace the `action_post_order` call with `action_post_selected_orders`, which posts each order individually and skips ones already sent to eTIMS, correctly handling both the refund case (original order is already `sent`) and the offline multi-order sync case. opw-6364221
Invoice tax recalculations using Avatax now refresh the pre-tax base amount instead of keeping an outdated value. This helps prevent invoices from remaining stuck with incorrect tax totals after recomputing taxes or reconfirming a draft invoice.
Original PR description
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of.…
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of. In some cases, the `manual_total_excluded_currency` value can end up incorrect (cause unknown). When this occurs, clicking "Compute Taxes" or resetting the invoice to draft and reconfirming does not correct the problem. This leaves the invoice in a persistently incorrect state with no straightforward way to fix it. Explanation: The bug is in `_process_external_taxes` in the `account_external_tax_mixin.py` in the `account_external_tax` module. During tax re-computation, if `extra_tax_data` is considered still valid, it is used to populate an in-memory base line dict. In this dict, `manual_tax_amounts` (which comes from a sub-dict in `extra_tax_data`) is explicitly cleared and fully repopulated from the fresh Avatax response every time. However, `manual_total_excluded_currency` in the base line dict is only updated if it is `None`. So, if it has an positive incorrect value, it will not be updated using the fresh Avatax response. Then, it will be written back to `extra_tax_data` unchanged, perpetuating the problem. Solution: Reset `manual_total_excluded_currency` to `None` at the start of each re-computation loop, mirroring what is already done for `manual_tax_amounts`. This ensures the pre-tax base amount is always taken from the current Avatax response rather than a previous value. This makes the behavior of `manual_tax_amounts` and `manual_total_excluded_currency` consistent with each other. opw-6235597