Daily updates from Odoo
Tuesday, July 28, 2026
290 changes
13 changes
Resolved issues and error corrections
This fix prevents branch-only users in Ecuadorian companies from being blocked when creating customer invoices. It keeps invoice creation working in parent-child company setups by reading the needed country information without requiring access to the parent company.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This fix updates an internal tracking hook in Planning Field Service so it matches the latest mail activity logging behavior. It helps ensure status changes continue to be recorded correctly without changing how users work.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This change fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep release validation stable and reduces false alarms during quality checks, without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Belgian payroll now correctly assigns an employee's DMFA work location when a matching work address is used on a new contract version. This helps ensure payroll location and working region information is accurate without requiring a manual address update.
Original PR description
After creating a dmfa location unit, creating a new version for an employee with the matching address_id should have self.l10n_be_location_unit and self.l10n_be_working_region set to the new value. For now, the field is only recomputed when updating address_id field.
- Steps to reproduce:
- With l10n_be_hr_payroll installed, create an employee in a BE company.
- Create a dmfa work location for the employee work address.
- Create a new contract for that employee.
- Employee l10n_be_location_unit field is still False.
- Cause: the compute method is triggered only on address_id field update.
- Solution: add `address_id.l10n_be_dmfa_location_unit_ids` to the depends decorator of the compute method.
Task: 6360653Payroll module upgrades are now protected from a crash caused by warning checks running too early. This helps businesses complete payroll updates more reliably, especially when optional payroll features are installed.
Original PR description
task-6345962
This fix updates an internal payroll test to use its own employee data instead of reusing an employee with existing payroll values. It helps keep India payroll percentage checks accurate and stable without changing payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124330 Forward-Port-Of: odoo/enterprise#121918
Mexican electronic invoicing now correctly updates the Tax Object field when a product’s unit price is added after an invoice was first saved. This helps keep invoices accurate and reduces manual corrections for compliance-related tax information.
Original PR description
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a…
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a new invoice and add a product that has no Unit Price. - Save the invoice. - Edit the same invoice, set a Unit Price for the product, and save it again. - Issue: The Tax Object field is not automatically set after the Unit Price is added. **Description:** - In our standard code, there is a condition that skips computing the Tax Object when the Unit Price is [0](https://github.com/odoo/enterprise/blob/615a5f756d708db95e22cdbdd6e7aca72ac769ec/l10n_mx_edi/models/account_move.py#L988). This is the expected behavior. - However, after setting a Unit Price on the product, the Tax Object is not recomputed, so it remains unset. - To resolve this issue, I added price_unit to the @api.depends decorator so that the Tax Object is recomputed whenever the Unit Price changes. **Reference videos:** Before the fix: [screen-capture (2).webm](https://github.com/user-attachments/assets/c1162fd9-52b8-4a8c-9ac2-39cf2ca3ad69) After the fix: [screen-capture (1).webm](https://github.com/user-attachments/assets/1c05dc34-6778-487a-9bfc-635cf652e670) OPW -6305080 UPG - 4268848 Forward-Port-Of: odoo/enterprise#125530 Forward-Port-Of: odoo/enterprise#123009
The Twitter social integration now disables the reply option for tweets where replies are not permitted by Twitter, such as tweets that do not mention the company account or quote one of its tweets. This helps prevent failed or inappropriate automated responses and keeps user actions aligned with Twitter rules.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
This update prevents occasional errors when a signing PDF preview is closed or detached at just the wrong moment. It improves the reliability of automated checks and helps keep the Sign app stable without changing user-facing behavior.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This update corrects Swedish ISO 20022 payment files so they match Swedbank's required identifiers and scheme values. It reduces the risk of bank payment files being rejected and also updates Swedish address formatting ahead of upcoming structured address requirements.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125676
Forward-Port-Of: odoo/enterprise#122119This fix prevents the timesheet assistant from crashing when away-time activity is processed without an expected unmatched group. Users can continue reviewing and categorizing time entries without interruption.
Original PR description
Before this commit, when the unmatched group is not found in events before processing afk event, a traceback occurs saying `Cannot read properties of undefined (reading 'Away (afk status 1)')` This commit moves the code checking the group key exists in `this.state.grouped` after processing afk event and before adding the afk event in unmatched group. Forward-Port-Of: odoo/enterprise#124072 Forward-Port-Of: odoo/enterprise#123452
Resetting a tax return now only removes accounting entries that were created for recoverable amounts from earlier tax returns. This prevents invoices or other reconciled entries from being accidentally deleted, protecting accounting records from unintended data loss.
Original PR description
Issue: Moves having a line reconciled to a tax return are unlinked if the tax return is reset. Steps to reproduce: - Set the tax account as reconcilable - Create an invoice for previous month and confirm it - Create a tax return for the previous month - Reconcile one of the invoice tax line to the tax return closing move. - Remove the lock date - Reset the tax return Current behavior: - all moves reconciled with the tax return are unlinked Expected behavior: - only moves comming from recoverable amount of previous tax returns should be unlinked opw-6370289 Forward-Port-Of: odoo/enterprise#123947
Fixes several issues affecting cumulative translation adjustment lines in financial reports. Trial balance and general ledger outputs now better respect horizontal groups, search filters, and fiscal-year dates, reducing the risk of confusing or incorrect report totals.
Original PR description
The engine for the cumulative translation adjustment line was fully overriding the forced options, but this key might already be present in the options, for example, when using horizontal groups. task-6418960 Forward-Port-Of: odoo/enterprise#124108
25 changes
Resolved issues and error corrections
This fixes an internal test setup for Indian payroll so percentage calculations are checked using dedicated sample employee data. It helps prevent unrelated employee payroll values from affecting test results, without changing actual payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124062 Forward-Port-Of: odoo/enterprise#121918
Uploading a document while Auto Sort is enabled no longer causes an error when the file is automatically moved to another folder. This keeps the Documents workflow stable and avoids interrupting users after sortable uploads.
Original PR description
When Auto Sort is enabled, an uploaded document can be moved to a different folder as part of the sort. The subsequent model reload only fetches records for the current folder to select/scroll to the new record. But, the new document's is absent from `env.model.root.records`. `newRecords` ends up empty, making `newRecords[0]` undefined, which then crashes accessing record.resId. To fix this, we just return early because if the record isn't in the current folder, there's nothing to select or scroll to anyway, so returning early here doesn't change anything visible behavior, it just avoids the crash. Steps to reproudce: 1.Go to Documents. 2.Go to Company->Inbox 3.Go to the gear icon and make sure the "Auto Sort" is enabled with "Move to folder" 4.Add a new document that's sortable. 5.You'll get the error. opw-6281558 Forward-Port-Of: odoo/enterprise#121069
Mexican invoice lines now correctly update the Tax Object field when a unit price is added after the invoice was first saved. This helps ensure invoices reflect the right tax classification without manual correction, reducing errors in Mexican electronic invoicing workflows.
Original PR description
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a…
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a new invoice and add a product that has no Unit Price. - Save the invoice. - Edit the same invoice, set a Unit Price for the product, and save it again. - Issue: The Tax Object field is not automatically set after the Unit Price is added. **Description:** - In our standard code, there is a condition that skips computing the Tax Object when the Unit Price is [0](https://github.com/odoo/enterprise/blob/615a5f756d708db95e22cdbdd6e7aca72ac769ec/l10n_mx_edi/models/account_move.py#L988). This is the expected behavior. - However, after setting a Unit Price on the product, the Tax Object is not recomputed, so it remains unset. - To resolve this issue, I added price_unit to the @api.depends decorator so that the Tax Object is recomputed whenever the Unit Price changes. **Reference videos:** Before the fix: [screen-capture (2).webm](https://github.com/user-attachments/assets/c1162fd9-52b8-4a8c-9ac2-39cf2ca3ad69) After the fix: [screen-capture (1).webm](https://github.com/user-attachments/assets/1c05dc34-6778-487a-9bfc-635cf652e670) OPW -6305080 UPG - 4268848 Forward-Port-Of: odoo/enterprise#125098 Forward-Port-Of: odoo/enterprise#123009
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It improves reliability for users working with cap table or equity transaction data by avoiding unexpected crashes during price calculation.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
This fix prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps ensure payroll data can continue to be handled smoothly without unexpected error screens for users.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
The trial balance report now handles load-more rows that have empty column data, preventing an error in the Colombian partner-grouped variant. This lets users continue expanding accounts and viewing additional report lines without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
This fix ensures Brazilian Avalara tax requests keep required customer tax settings even when their values are empty or false. This prevents Avalara from assigning the wrong CFOP code, helping invoices use the correct fiscal classification.
Original PR description
## Steps to reproduce: 1. Install `l10n_br`, `l10n_br_avatax`, and `l10n_br_edi_fiscal_reform`. 2. Ensure that Demo mode is activated if not on Runbot. 3. Navigate to Contacts, then click into "BR…
## Steps to reproduce:
1. Install `l10n_br`, `l10n_br_avatax`, and `l10n_br_edi_fiscal_reform`.
2. Ensure that Demo mode is activated if not on Runbot.
3. Navigate to Contacts, then click into "BR Company Customer Estimated Profit".
4. Duplicate this contact, then set the following fields:
1. Tax Regime set to individual
2. ICMS Taxpayer Type set to Non-Taxpayer
5. Swtich to the BR Company and go to Accounting / Configuration / Settings.
6. Set up a Sandbox Avalara account and enable logging payload responses.
7. Navigate to Accounting > Customers > Invoices.
8. Create an invoice with:
1. Customer set to the copy created earlier.
2. Operation Type set to Sale of Goods
3. Document Type set to 55
4. Payment Method Brazil set to Money
5. Presence set to Present
6. One sales order line with:
1. Regular Consumable Product
2. quantity set to 1
3. price set to 100.0
9. Confirm the invoice.
10. Navigate back to Accounting > Configuration > Settings to view the response from Avalara. The customer will have the CFOP 6102 instead of CFOP 6108.
Explanation:
PR #97845 introduced `_l10n_br_deep_clean_dict()` to remove falsy values and empty dictionaries from the payload we send to Avalara. This fix was applied as broadly as possible to prevent excessive if statements.
However, if the falsy values in taxSettings of the customer are not communicated, Avalara will assign the customer to an incorrect CFOP.
opw-6085964
Forward-Port-Of: odoo/enterprise#124730
Forward-Port-Of: odoo/enterprise#120783Customers can no longer complete payment for planning-based rental services when the required resources are already booked. The cart now blocks checkout until the customer chooses an available date or lowers the quantity, preventing failed orders after payment.
Original PR description
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The…
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The cart lets them increase the quantity past the available capacity and proceed all the way through checkout without any availability gate. **Steps to reproduce:** 1. Install `website_sale_renting_planning`. 2. Create a planning role with `sync_shift_rental` and one resource. 3. Create a service product with `rent_ok=True`, `planning_enabled=True` and the role above. 4. Pre-book the resource for some window via a `planning.slot`. 5. From eCommerce, add the product to the cart for the same window. 6. Proceed to checkout/payment. **Current behavior:** The cart is considered ready, no warning is shown, and payment can proceed even though no planning resource is free for the chosen period. **Expected behavior:** The cart should be flagged as not ready and pre-payment validation should refuse to confirm until the customer picks a different date or quantity. **Cause of the issue:** `sale.order._available_dates_for_renting` in `website_sale_renting` is the documented hook for "stock availability" gating of the cart and pre-payment flow (called from `_is_cart_ready` and from `_check_cart_is_ready_to_be_paid`). `website_sale_stock_renting` overrides it to apply a per-line stock check, but `website_sale_renting_planning` has no such override, so planning-backed rental services reach payment with no availability gate at all. **Fix:** Apply the same gating pattern that `website_sale_stock_renting` already uses: override `_available_dates_for_renting` in `website_sale_renting_planning` so that, for each rental line whose product is a planning-synced rentable service, the cart is only considered valid when at least the requested quantity of planning resources is free during the rental window (mirroring the resource and leave filtering already done by `_planning_slot_vals_list_per_sol` at SO confirmation time). This puts the gate at the same point the stock-renting flow enforces it, keeping the public cart/checkout flow consistent across rentable product types. opw-6247034 Forward-Port-Of: odoo/enterprise#125534 Forward-Port-Of: odoo/enterprise#118943
Mexican electronic invoice fields are now placed in the correct invoice header area regardless of other localization modules installed. This prevents the CFDI Origin field from disappearing on Mexican invoices when Colombian localization features are also present.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
This change adds a test to ensure financial reports handle changing domestic currency rates correctly. It helps prevent incorrect currency translation adjustment values when exchange rates fluctuate during the reporting period.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#123055
Resetting a tax return now only removes entries created from recoverable amounts of previous tax returns, instead of deleting other reconciled accounting moves. This helps preserve valid invoice accounting records when businesses reset or correct a tax return.
Original PR description
Issue: Moves having a line reconciled to a tax return are unlinked if the tax return is reset. Steps to reproduce: - Set the tax account as reconcilable - Create an invoice for previous month and confirm it - Create a tax return for the previous month - Reconcile one of the invoice tax line to the tax return closing move. - Remove the lock date - Reset the tax return Current behavior: - all moves reconciled with the tax return are unlinked Expected behavior: - only moves comming from recoverable amount of previous tax returns should be unlinked opw-6370289 Forward-Port-Of: odoo/enterprise#123947
Uruguayan export invoices that are fully offset by discounts can now be generated with the required discount details. This helps exporters submit valid electronic invoices to Uruware even when the final invoice total is zero.
Original PR description
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not…
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not handled correctly by the XML/CFE generation logic. This use case is valid and required by exporters who need to reflect the declared value of goods/services while invoicing at zero (e.g. to comply with customs or incoterm requirements such as FCA). In Uruware's validation portal, the "Descuentos y Recargos" (discounts & surcharges) section of the subtotal block must be correctly populated for the CFE to be accepted. **Example:** An invoice with a line of 648.00 UYU and a global discount of −648.00 UYU → Total: 0.00. The export value is still declared, taxes are zero, but the CFE must reflect the discount amount explicitly. <img width="592" height="679" alt="example_expo_invoice_discount" src="https://github.com/user-attachments/assets/aa83c158-e342-4da5-a251-fc209bbed5c4" /> ## Root Cause The CFE template (`cfe_template.xml`) and the move computation logic (`account_move.py`) did not account for the case where export invoices carry line-level or global discounts that zero out the total. The discount amount was either omitted from the XML nodes or computed incorrectly, causing Uruware validation to fail or the discount block to not render. ## Fix - **`l10n_uy_edi/models/account_move.py`** — Updated the export invoice computation to correctly include discount amounts in the CFE data dict, ensuring the `ValorDR` is filled with the value of the discount per line. - **`l10n_uy_edi/views/cfe_template.xml`** — Adjusted the template condition so `MntExpoyAsim` node accepts 0 as value. ## Steps to Reproduce (before fix) 1. Create an export invoice (e-Factura Exportación) for a foreign partner. 2. Add a product line with a unit price, e.g. 216.00 × 3 = 648.00 UYU. 3. Add a global discount of 648.00 (same amount) so the total is 0.00. 4. Confirm and send to Uruware — the CFE is rejected / discount block is missing. ## Verification After the fix, the same invoice generates a valid CFE accepted by Uruware with the discount correctly reflected in the `DscRcgGlobal` node and the discount line visible on the printed document. Forward-Port-Of: odoo/enterprise#124910 Forward-Port-Of: odoo/enterprise#120130
The Belgian minimum salary warning will now only appear for employees using Belgian payroll rules. This prevents irrelevant alerts from showing for employees in other countries, reducing confusion for HR users.
Original PR description
[FIX] l10n_be: fix min salary warning appearance in other l18n Bug reproduc: 1 - Install l10n_be_hr_payroll 2 - Go to some US employee, make its wage to 10. 3 - The warning "Annual salary is below 34654" will be there. Bug cause: 1 - The issue is created without controlling the country of the version Bug solution: 1 - Add Belgium country check to the issue creation task-6412374
This update fixes an unreliable automated tour test in Web Studio. It helps reduce false failures in validation pipelines, making releases and quality checks more dependable without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
This fix prevents branch-level users in Ecuadorian companies from being blocked by an access error when creating customer invoices. It lets the invoicing flow use the journal's country information safely, even when the journal belongs to a parent company the user cannot access.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This fix prevents an occasional timing issue from causing errors when the signing document viewer closes or reloads at just the wrong moment. It improves stability for Odoo Sign and helps keep automated validation runs clean without changing user-facing behavior.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
The Twitter integration now disables the reply option when Twitter rules do not allow a response, such as when the account is not mentioned or quoted. This helps prevent failed replies and reduces the risk of unwanted automated messages to Twitter users.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
Swiss payroll contract templates now show the same relevant wage fields as the employee contract view and correctly transfer those values when a template is loaded. This helps payroll teams avoid missing or incorrect wage information when creating employee contracts from templates.
Original PR description
## Issue When creating a Contract Template for a Swiss company, the template does not match the version shown in the Employee's view. Also, some fields are not correctly applied when loading a…
## Issue
When creating a Contract Template for a Swiss company, the template does not match the version shown in the Employee's view. Also, some fields are not correctly applied when loading a contract template on an employee (e.g. `hourly_wage`, `wage`, ...).
## Steps to reproduce
1. Install *Switzerland - Swissdec Certified ELM 5.0 - Payroll* (`l10n_ch_hr_payroll`)
2. (Create and) Use a Swiss company
3. In Employees > Configuration > Contract Templates, create a Contract Template
- Wage Type: Hourly Wage
- Hourly Wage: Any value > 0
- **(Notice how the aforementionned fields are missing from the template)**
4. In Employees > Employees, create an Employee
5. On the new employee's view, on the Payroll tab, click "Load Template"
and load the template created in step 3
6. **The data from the template is not applied to the employee's contract**
## Cause
The fields loaded from a contract template are listed in the `whitelist` variable of the `hr.version.wizard`:
https://github.com/odoo/odoo/blob/5c3deb11627f4d6762c4994207bd582afb96f064/addons/hr/wizard/hr_contract_template_wizard.py#L15-L30
Multiple fields were missing from the whitelist (e.g. `hourly_wage`, `l10n_ch_has_{hourly|monthly|lesson}`, ...). These fields would not be loaded from the template when applying a template on an employee.
**This commit replicates the employee's version view on the contract template and adds the related fields to the whitelist for them to be correctly applied when loading a contract template.**
opw-5966664
opw-6128467
Forward-Port-Of: odoo/enterprise#125212
Forward-Port-Of: odoo/enterprise#110683Swedish ISO 20022 payment files are adjusted to meet Swedbank requirements, helping companies avoid rejected payments. The update also prepares Swedish payment files for upcoming structured address rules from November 2026.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125676
Forward-Port-Of: odoo/enterprise#122119Spanish VAT record books now include taxable accounting entries created outside standard invoices and bills, such as Point of Sale session closures. This helps businesses produce more complete VAT records and avoid missing tax-relevant POS transactions in Excel exports.
Original PR description
Currently, the Spanish VAT record books (Libros Registro de IVA) only include move types associated with invoices and bills. However, miscellaneous entries (type 'entry'), such as those generated by the Point of Sale session closures or manual liquidations, also carry tax obligations and must be reflected in these reports. Steps to reproduce: - Open a POS Session - Create an order, pay and close session - Go to Accouting > Reporting > Tax report - Select Generic Tax report - Print "VAT record Books" Issue: Only invoices and bills are visible in the excel file, and not the entry generated from point of sale. However, movements that are not related to invoices should be included in the VAT books. opw-5862529 Forward-Port-Of: odoo/enterprise#125631 Forward-Port-Of: odoo/enterprise#113681
Vehicle references on invoice lines are no longer clickable while an invoice is still in draft. This keeps draft invoice behavior consistent with product links and helps prevent users from navigating to vehicle records before the invoice is finalized.
Original PR description
The vehicle under account on the invoice lines should not be clickable when the invoice is in draft. Only when it is posted, like the product. task-6385436 Forward-Port-Of: odoo/enterprise#124514
Belgian payroll calculations now apply withholding tax reductions for disabled employees, disabled spouses, and spouses with low or no income even when there are no dependent children or seniors. This helps ensure affected employees receive the correct net pay and updates the wording for spouse fiscal situation thresholds.
Original PR description
Prior to this commit, the reductions for disabled employees, disabled spouse, and spouse with low or no income did not apply if the employee did not have any depenedent juniors or seniors. This commit fixes that, by removing the unneeded condition, and applying the reductions for those employees. This commit also updates the text for the thresholds of the spouse's fiscal situation. task-6384236 task-6320606 Forward-Port-Of: odoo/enterprise#124803
Guatemalan credit notes now reference the original invoice's actual issue date instead of a technical certification timestamp. This helps ensure documents meet SAT validation requirements and avoids rejections caused by mismatched dates.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409 Forward-Port-Of: odoo/enterprise#124794
Odoo now handles Chilean electronic tax documents that arrive without a recipient tax ID without crashing the scheduled email processing job. This prevents one malformed customer claim email from repeatedly blocking the whole mailbox and allows the existing missing-partner handling to continue normally.
Original PR description
### Problem `Mail: Fetchmail Service` cron aborts with `AttributeError: 'NoneType' object has no attribute 'upper'` in `l10n_cl_edi/models/fetchmail_server.py::_process_incoming_customer_claim` when…
### Problem
`Mail: Fetchmail Service` cron aborts with `AttributeError: 'NoneType' object has no attribute 'upper'` in `l10n_cl_edi/models/fetchmail_server.py::_process_incoming_customer_claim` when an incoming customer claim DTE has no `<RUTRecep>`:
```python
dte.findtext('.//ns0:RUTRecep', ...).upper() or
dte.findtext('.//ns0:RutReceptor', ...).upper()
```
`findtext()` returns `None` when the tag is missing, so `.upper()` blows up before the `or` fallback can run. Once the cron hits such a message it re-crashes on every subsequent run and blocks the whole mailbox until the offending mail is deleted.
### Fix
Guard each `findtext(...)` with `or ''` so the `or` chain actually falls through. Empty `partner_vat` is already handled by the existing "Partner … has not been found" branch a few lines below.
### Traceback (Odoo 19)
```
File "/mnt/extra-addons/enterprise/l10n_cl_edi/models/fetchmail_server.py", line 285, in _process_incoming_customer_claim
dte.findtext('.//ns0:RUTRecep', namespaces=XML_NAMESPACES).upper() or
AttributeError: 'NoneType' object has no attribute 'upper'
```
### Ticket
No ticket open for this but opw-5257481 is related.
Forward-Port-Of: odoo/enterprise#123387Fixed an issue where sales order information could be hidden on planning slot forms for companies using a single-company setup. This ensures users can consistently see and use the relevant sales order field regardless of company configuration.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673 Forward-Port-Of: odoo/enterprise#125712
27 changes
Resolved issues and error corrections
Updates Swedish ISO 20022 payment files so they match Swedbank's required identifiers and bank scheme values. This helps Swedish payment exports be accepted by banks and also prepares Swedish payment XML address formatting for upcoming structured address requirements.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125561
Forward-Port-Of: odoo/enterprise#122119Adds a validation test to ensure reports calculate currency translation adjustments correctly when the company's domestic currency rate changes during the year. This helps prevent overstated or understated financial reporting figures in multi-currency scenarios.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#123055
Mexican electronic invoicing fields are now placed in a stable invoice header area instead of depending on the order of installed localization modules. This prevents the CFDI Origin field from disappearing on Mexican invoices when the Colombian localization is also installed.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
Uruguayan electronic export invoices with discounts that reduce the total to zero now generate the required discount information correctly. This helps exporters issue compliant documents for customs or incoterm-related cases and avoids validation failures in Uruware.
Original PR description
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not…
## Problem When generating an export CFE (e-Factura Exportación) in the Uruguayan EDI module, invoices that include a discount line equal to the subtotal — resulting in a **total of 0.00** — were not handled correctly by the XML/CFE generation logic. This use case is valid and required by exporters who need to reflect the declared value of goods/services while invoicing at zero (e.g. to comply with customs or incoterm requirements such as FCA). In Uruware's validation portal, the "Descuentos y Recargos" (discounts & surcharges) section of the subtotal block must be correctly populated for the CFE to be accepted. **Example:** An invoice with a line of 648.00 UYU and a global discount of −648.00 UYU → Total: 0.00. The export value is still declared, taxes are zero, but the CFE must reflect the discount amount explicitly. <img width="592" height="679" alt="example_expo_invoice_discount" src="https://github.com/user-attachments/assets/aa83c158-e342-4da5-a251-fc209bbed5c4" /> ## Root Cause The CFE template (`cfe_template.xml`) and the move computation logic (`account_move.py`) did not account for the case where export invoices carry line-level or global discounts that zero out the total. The discount amount was either omitted from the XML nodes or computed incorrectly, causing Uruware validation to fail or the discount block to not render. ## Fix - **`l10n_uy_edi/models/account_move.py`** — Updated the export invoice computation to correctly include discount amounts in the CFE data dict, ensuring the `ValorDR` is filled with the value of the discount per line. - **`l10n_uy_edi/views/cfe_template.xml`** — Adjusted the template condition so `MntExpoyAsim` node accepts 0 as value. ## Steps to Reproduce (before fix) 1. Create an export invoice (e-Factura Exportación) for a foreign partner. 2. Add a product line with a unit price, e.g. 216.00 × 3 = 648.00 UYU. 3. Add a global discount of 648.00 (same amount) so the total is 0.00. 4. Confirm and send to Uruware — the CFE is rejected / discount block is missing. ## Verification After the fix, the same invoice generates a valid CFE accepted by Uruware with the discount correctly reflected in the `DscRcgGlobal` node and the discount line visible on the printed document. Forward-Port-Of: odoo/enterprise#124910 Forward-Port-Of: odoo/enterprise#120130
Swiss contract templates now match the employee payroll view and correctly carry over wage-related details when loaded onto an employee contract. This prevents missing or incorrect payroll setup for Swiss employees, especially for hourly wage contracts.
Original PR description
## Issue When creating a Contract Template for a Swiss company, the template does not match the version shown in the Employee's view. Also, some fields are not correctly applied when loading a…
## Issue
When creating a Contract Template for a Swiss company, the template does not match the version shown in the Employee's view. Also, some fields are not correctly applied when loading a contract template on an employee (e.g. `hourly_wage`, `wage`, ...).
## Steps to reproduce
1. Install *Switzerland - Swissdec Certified ELM 5.0 - Payroll* (`l10n_ch_hr_payroll`)
2. (Create and) Use a Swiss company
3. In Employees > Configuration > Contract Templates, create a Contract Template
- Wage Type: Hourly Wage
- Hourly Wage: Any value > 0
- **(Notice how the aforementionned fields are missing from the template)**
4. In Employees > Employees, create an Employee
5. On the new employee's view, on the Payroll tab, click "Load Template"
and load the template created in step 3
6. **The data from the template is not applied to the employee's contract**
## Cause
The fields loaded from a contract template are listed in the `whitelist` variable of the `hr.version.wizard`:
https://github.com/odoo/odoo/blob/5c3deb11627f4d6762c4994207bd582afb96f064/addons/hr/wizard/hr_contract_template_wizard.py#L15-L30
Multiple fields were missing from the whitelist (e.g. `hourly_wage`, `l10n_ch_has_{hourly|monthly|lesson}`, ...). These fields would not be loaded from the template when applying a template on an employee.
**This commit replicates the employee's version view on the contract template and adds the related fields to the whitelist for them to be correctly applied when loading a contract template.**
opw-5966664
opw-6128467
Forward-Port-Of: odoo/enterprise#125212
Forward-Port-Of: odoo/enterprise#110683Belgian payroll calculations now correctly apply withholding tax reductions for disabled employees, disabled spouses, and spouses with low or no income even when there are no dependent children or seniors. The update helps ensure affected employees receive the right payroll tax treatment and clarifies spouse income threshold wording.
Original PR description
Prior to this commit, the reductions for disabled employees, disabled spouse, and spouse with low or no income did not apply if the employee did not have any depenedent juniors or seniors. This commit fixes that, by removing the unneeded condition, and applying the reductions for those employees. This commit also updates the text for the thresholds of the spouse's fiscal situation. task-6384236 task-6320606
The Payroll dashboard now handles structure types that do not have a scheduled pay value set. This prevents the dashboard from crashing and lets payroll teams continue using payroll warnings and closing date information normally.
Original PR description
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to…
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to Payroll > Configuration > Settings > Set Payroll Closing Date > Save - Go to Payroll > Configuration > Structure Types > Create a new Structure Type > Unset Scheduled Pay - Open Dashboard Traceback: ```py AttributeError: 'bool' object has no attribute 'title' ``` https://github.com/odoo/enterprise/blob/9a3ea83a432f42f62076a50fca6bc771a2de96bf/hr_payroll/models/hr_payroll_warning.py#L413-L419 The dashboard collects the scheduled pay values from all structure types and later calls ``schedule.title()`` to build the labels. When a Structure Type has no Scheduled Pay configured, so ``schedule`` becomes ``False``, leading to the traceback. ``_get_schedule_pay`` method can return False at [1], So, It will generate the traceback from below line also. https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L401 Solution: Added a fallback value when default scheduled pay is False. [1]: https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L149-L154 sentry-7583037488
Sales order information on planning slot forms is now visible for single-company users. This prevents important sales details from being hidden because of company configuration, making scheduling linked to sales orders more reliable.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673
Peppol purchase settings now correctly decide when a journal is required, especially when French PDP features and Documents integration are both installed. This prevents non-French companies using Peppol with a Documents folder from being incorrectly forced to select an invoicing journal, and ensures document-based imports stay in Documents only.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479 Forward-Port-Of: odoo/enterprise#120722
The Belgian payroll rules have been adjusted so the 3000 deduction is calculated correctly for the second and third quarters of 2026. This helps ensure payroll reporting and related filings remain accurate for Belgian employers.
Original PR description
Forward-Port-Of: odoo/enterprise#124034
This fix prevents users assigned only to an Ecuadorian company branch from being blocked when creating customer invoices. It keeps normal invoicing workflows working in parent–branch company setups without requiring broader company access.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This update prevents occasional errors when the Sign PDF viewer is closed or detached while it is still loading. It improves stability in automated testing and reduces the chance of users encountering unexpected Sign document viewing issues.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
The Twitter integration now disables the reply option when Twitter rules do not allow a response, such as when the account was not mentioned or quoted. This helps prevent failed reply attempts and reduces the risk of automated messages being sent where they are not permitted.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
This fixes an issue in Mexican payroll where clearing a payslip start or end date could trigger an error and interrupt the workflow. The system now checks that required dates are present before running the salary-limit warning calculation, helping payroll users edit payslips safely.
Original PR description
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI`…
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI` company - Go to `Payslips`, create a payslip. - Set an `employee`, and remove either the `start date` or the `end date` from Period.. `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` After the [recent commit] adding a warning about the employee exceeding the salary limit, when the user removes the dates from the payslip, the compute method attempts to compute the warning from [1], and when it adds relativedelta to date_from, which is False, it raises the error [2]. This commit ensures that the payslip dates are checked first before adding relativedelta to the date and performing the comparison. [recent commit]: https://github.com/odoo/enterprise/commit/6abfa47dafe439f9328d606ef6ac5126ec6eb1f6 [1]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/hr_payroll/models/hr_payslip.py#L1446 [2]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py#L272-L276 Forward-Port-Of: odoo/enterprise#124187 Forward-Port-Of: odoo/enterprise#122643
Updated AI tool descriptions to remove misleading labels that could cause automated agents to call the wrong function. This helps improve reliability when AI agents search or group records in Odoo.
Original PR description
Purpose: -------- Agents occasionally fail by trying to call a `search` tool that does not exist. This seems to come from the `Tool Name: search` header in the tool description, which can be confused with the actual tool name used by the LLM, i.e. the tool xmlid. This commit removes these headers from the search and read group tool descriptions. They were missed in [this commit](https://github.com/odoo/enterprise/commit/912bce43a98d45e90dbd24328fa2f46caba4c887 ), which removed the same headers from the other tools. Task-6401285 Forward-Port-Of: odoo/enterprise#125110
Guatemalan credit notes now reference the original invoice’s actual issue date instead of a technical certification timestamp. This helps ensure documents meet SAT validation rules and reduces the risk of rejected electronic credit notes.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409 Forward-Port-Of: odoo/enterprise#124794
Opening the Scrap action from a new manufacturing barcode operation no longer triggers an error when no location record is available. This prevents interruptions for users creating manufacturing orders or scanning products, including cases with consignment enabled.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Open Barcode app; 2. click Operations; 3. click MANUFACTURING 4. click New; 5. click cogwheel on top right; 6. click Scrap. Issue ----- Traceback: > Error: Record stock.location with id=undefined doesn't exist in the cache Cause ----- When setting up the default context for the scrap menu, it it assumes `this.record` is not empty. Solution -------- Make `cache.getRecord` not raise an error when a location isn't found. Use optional chaining for other parts of the context that rely on a `record` being present. Also fixes a related issue introduced by 4b457fe, where the same traceback would be thrown on opening a new MO and scanning a product whilst consignment is enabled. opw-6397774 Forward-Port-Of: odoo/enterprise#125571 Forward-Port-Of: odoo/enterprise#124818
Spanish VAT record books now include tax entries created outside standard invoices and bills, such as Point of Sale session closing entries. This helps businesses produce more complete VAT records and reduces the risk of missing taxable POS activity in reports.
Original PR description
Currently, the Spanish VAT record books (Libros Registro de IVA) only include move types associated with invoices and bills. However, miscellaneous entries (type 'entry'), such as those generated by the Point of Sale session closures or manual liquidations, also carry tax obligations and must be reflected in these reports. Steps to reproduce: - Open a POS Session - Create an order, pay and close session - Go to Accouting > Reporting > Tax report - Select Generic Tax report - Print "VAT record Books" Issue: Only invoices and bills are visible in the excel file, and not the entry generated from point of sale. However, movements that are not related to invoices should be included in the VAT books. opw-5862529 Forward-Port-Of: odoo/enterprise#125631 Forward-Port-Of: odoo/enterprise#113681
The timesheet sample data button now works even when ActivityWatch is connected. Users can add sample events alongside real activity data, making demos and testing easier without disconnecting ActivityWatch.
Original PR description
Before this commit, the Generate Sample Data button only worked when the ActivityWatch server was unavailable. When ActivityWatch was running, users could only load real activity data. After this commit, clicking Generate Sample Data while ActivityWatch is connected injects the generated sample events alongside the real ActivityWatch events, allowing both to be displayed together. task-6373606
The Vietnam Sales Tax Report now keeps VAT base amounts positive at the detailed invoice level, matching the totals shown higher in the report. This removes a confusing negative display for sales VAT and helps users review Vietnamese tax reporting figures more confidently.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#122785
The Belgian Partner VAT Listing now always covers the required calendar year from January 1 to December 31. This prevents incorrect reporting periods for businesses whose fiscal year does not match the calendar year, helping improve compliance accuracy.
Original PR description
The Belgian Partner VAT Listing must always report on the civil calendar year (01/01/N to 12/31/N). Previously, the report was relying on the company's fiscal year configuration, which caused incorrect reporting periods for companies with non-calendar fiscal years. This commit overrides `_custom_options_initializer` to strictly enforce a civil year date range based on the selected year, entirely ignoring custom fiscal year boundaries. Task-6086513 Forward-Port-Of: odoo/enterprise#114337
This fix ensures Manufacturing Planning Schedule calculations use a product's Bill of Materials batch size even when the BOM was not manually selected. This prevents underestimating replenishment quantities and helps manufacturing teams plan production more accurately.
Original PR description
In MPS, if a product’s Bill of Materials (BOM) is not specified at the time of addition, the system will not correctly account for batch size. Steps to reproduce: ------------------- * Create a…
In MPS, if a product’s Bill of Materials (BOM) is not specified at the time of addition, the system will not correctly account for batch size. Steps to reproduce: ------------------- * Create a product with a bom that has a batch size of 2 * Open MPS * Add the product - without specifying the bom - Route Manufacture * Add 1 in the Forcast Demand -> the batch size from the bom it's not taken into account. Observation: ------------- When updating mps, it will call get_production_schedule_view_state: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L424 this function when calculating the quantity to resplenish will call _get_resplenish_qty: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L534 to know the quantity to resplenish it will need the batch size, in mps they will only consider the batch size from the bom registered: https://github.com/odoo/enterprise/blob/7092dd2cc3578c3f22d1fbc82d958d57e2f93553/mrp_mps/models/mrp_mps.py#L863-L865 Since there is no default value for bom_id, If there is no bom selected, there is no batch size. opw-6259956 Forward-Port-Of: odoo/enterprise#119560
This fix prevents timesheet-related automation from being affected by unread notification counts in Discuss. It helps avoid incorrect handling of timesheet reminders when message badges appear in the interface.
Original PR description
task: 6416889
Sales users without Planning permissions can now add products from the catalog on quotations created from field service planning slots. This prevents an access error and keeps the quotation workflow available to sales staff with limited planning rights.
Original PR description
A user without Planning rights cannot add a product from the catalog on a sale order Steps to reproduce: 1. Install planning_field_service_sale_timesheet module 2. Go to Settings > Users & Companies…
A user without Planning rights cannot add a product from the catalog on a sale order Steps to reproduce: 1. Install planning_field_service_sale_timesheet module 2. Go to Settings > Users & Companies > Users and open user Marc Demo 3. Set Planning rights to No 4. Go to Settings > Planning > Field Service and enable Quotations 5. Go to Planning, create a new planning slot with customer Acme Corporation, open it in fullscreen, click on the quotation smart button and create a new quotation 6. Log in as Marc Demo 7. Go to Sales and open the new quotation 8. Click on Catalog in the order lines 9. An access error is raised Issue: planning_field_service_sale_timesheet overrides `action_add_from_catalog` and tries to read sale.order.planning_slot_id but users can't always access this field as it either requires Administrator rights on Planning or that the planning.slot is not in draft https://github.com/odoo/enterprise/blob/e92a86257cb99ee1010531ec10d8fc968623a31d/planning/security/planning_security.xml#L60-L69 Solution: Check that the user has write rights before opening `action_view_material` opw-6315647 Forward-Port-Of: odoo/enterprise#123228
The timesheet assistant now uses the correct color cue for total hours, showing green when recorded time is below expected working hours. Flexible-hour schedules no longer receive an unnecessary color indicator, reducing confusion for employees and managers reviewing timesheets.
Original PR description
Fix the wrong color selection of total hours on the timesheet assistant page before: green if total time > working hours after: - green if total time < working hours - no color for flexible hours --- task-6409938
Fixes an error that could prevent users from viewing planning schedules grouped by role when a role had no assigned resource or no working calendar. This improves reliability of the Planning Gantt view and helps managers review schedules without interruptions.
Original PR description
Currently, an error occurs when grouping planning slots by role. **Steps to Reproduce:** - Install the `Planning` module. - Go to `Planning` > `Configuration` > `Roles`. - Create a `role` without…
Currently, an error occurs when grouping planning slots by role.
**Steps to Reproduce:**
- Install the `Planning` module.
- Go to `Planning` > `Configuration` > `Roles`.
- Create a `role` without assigning any resource to it (or assign a resource without a working time).
- Go to `Planning`, create a new `planning slot`, assign the `role` created above, set the start date to `20/07/2026 12:00 PM` and the end date to `21/07/2026 2:00 AM`.
- Switch to the `Gantt view` of the `planning slots`.
- Group by `Role` and set the custom date range to `07/19/2026 -> 07/20/2026`, then click `Apply`.
`KeyError: 1`
The error occurs when the user groups the planning slots by role in the Gantt view. During
the computation of the Gantt progress bar, if the existing slot's role has no resource, or has
a flexible resource without a calendar, the regular resources become empty [1]. Then it
attempts to compute the valid work intervals for these empty resources [2], resulting in an
empty calendar work interval dictionary ({}) [3]. Later, when computing the duration over the
period with the valid range slots, it tries to access the resource directly from the empty
calendar_intervals dictionary [4], which raises the error.
This commit ensures that, when no work intervals are available for a resource, an empty
work interval is used instead.
[1]- https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L307
[2]: https://github.com/odoo/odoo/blob/5663509fe5caa1191fafcea3b3879dcef9ceca8f/addons/resource/models/resource_resource.py#L220
[3]: https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L3415-L3417
[4]- https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L3300
sentry-7620222164Mexican payroll can now calculate expected work hours even before a draft payslip exists. This prevents missing or incorrect attendance information when creating off-cycle payroll, making payroll preparation more consistent.
Original PR description
Previously, the `_preprocess_work_hours_data` method would abort early if no payslip was found for the given period. This prevented the correct generation or evaluation of expected Mexican work hours…
Previously, the `_preprocess_work_hours_data` method would abort early if no payslip was found for the given period. This prevented the correct generation or evaluation of expected Mexican work hours in contexts where a draft payslip does not yet exist (i.e., when an off-cycle payslip is initially generated for a given time period). To resolve this, the strict dependency on the payslip record has been removed. It now falls back to the contract version's base data when a payslip is absent: - The calendar defaults to the contract version's `resource_calendar_id`. - The duration is assumed to be standard (`is_wrong_duration = False`). - The Mexican schedule table (`l10n_mx_schedule_table`) is fetched globally from the environment (`hr.rule.parameter`) rather than relying on the payslip-specific helper method. This ensures expected work hours and attendance fields are calculated consistently across all payroll workflows, regardless of whether the payslip has been instantiated. opw-6351402
14 changes
Resolved issues and error corrections
AI-generated replacements now preserve separate lines when updating checklist or list content, so translated or rewritten items do not get merged into one entry. The change also improves how AI remembers selected text without adding hidden layout elements, reducing visual glitches when working with longer selections.
Original PR description
When replacing text within a list, text is inserted as a sequence of text nodes. Because of this, all lines end up inside the same list item. This commit puts further lines of the AI response into paragraphs in order to have them end up in distinct list items. Steps to reproduce: - Go to the default "To Do" note - Select a few lines of the checkbox list - Click on the AI button in the toolbar - Ask to "translate to French" - Use this => All translated lines ended up on a single line. task-6364282
This update prevents occasional errors when the Sign document preview closes or reloads at the same time it is being prepared. It improves reliability in automated testing and reduces the chance of users encountering intermittent failures while opening signing requests.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
Ecuador branch users can now create customer invoices without being blocked by an access error. The fix avoids requiring access to the parent company when checking the journal country, keeping normal invoicing workflows working in branch setups.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
The expense Stripe cardholder field now uses the standard setup for selecting related records. This ensures any selection rules configured in the view are applied correctly, helping users see the right cardholder options.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Forward-Port-Of: odoo/enterprise#125346
The Twitter integration now disables the reply option when Twitter rules do not allow a response, such as when the account was not mentioned or the post does not quote one of its tweets. This helps prevent failed or inappropriate replies and reduces the risk of automated messages being sent where they are not permitted.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
The AI assistant guidance was cleaned up to remove misleading labels that could cause it to request a non-existent search action. This reduces avoidable agent failures and helps AI features behave more consistently.
Original PR description
Purpose: -------- Agents occasionally fail by trying to call a `search` tool that does not exist. This seems to come from the `Tool Name: search` header in the tool description, which can be confused with the actual tool name used by the LLM, i.e. the tool xmlid. This commit removes these headers from the search and read group tool descriptions. They were missed in [this commit](https://github.com/odoo/enterprise/commit/912bce43a98d45e90dbd24328fa2f46caba4c887 ), which removed the same headers from the other tools. Task-6401285 Forward-Port-Of: odoo/enterprise#125110
The Belgian Partner VAT Listing now always covers the required civil calendar year, from January 1 to December 31. This prevents incorrect reporting periods for companies whose fiscal year does not match the calendar year, helping improve compliance accuracy.
Original PR description
The Belgian Partner VAT Listing must always report on the civil calendar year (01/01/N to 12/31/N). Previously, the report was relying on the company's fiscal year configuration, which caused incorrect reporting periods for companies with non-calendar fiscal years. This commit overrides `_custom_options_initializer` to strictly enforce a civil year date range based on the selected year, entirely ignoring custom fiscal year boundaries. Task-6086513 Forward-Port-Of: odoo/enterprise#114337
The barcode app now shows the package type selection prompt when users choose Put in Pack and the delivery operation requires a package type. This prevents warehouse users from creating packages without the expected type and keeps barcode workflows aligned with standard inventory behavior.
Original PR description
### Steps to reproduce: - In the settings enable: Packages - On the operation type `Delivery Order` set "Set Package Type" - Create and confirm a delivery for 1 unit of a product P + reserve it - Got…
### Steps to reproduce: - In the settings enable: Packages - On the operation type `Delivery Order` set "Set Package Type" - Create and confirm a delivery for 1 unit of a product P + reserve it - Got to the barcode app to process the delivery - Scan your product and click "put in pack" #### > The put in pack wizard allowing you to set a package type on the new package does not pop up. ### Cause of the issue: As a general rule of thumb the wizard is suppose to be displayed when the option is enabled and when a package/package type is not already provided to the call: https://github.com/odoo/odoo/blob/5dbc448d336c7ff22803ae91d5014eb6d0a07234/addons/stock/models/stock_package.py#L332-L341 https://github.com/odoo/odoo/blob/5dbc448d336c7ff22803ae91d5014eb6d0a07234/addons/stock/models/stock_move_line.py#L1236-L1238 However an override was added to the barcode module so that the wizard is never displayed when the action is launched from the barcode app: https://github.com/odoo/enterprise/blob/673d449f38cd3eff27c44270c8f7edf91d0ecd02/stock_barcode/models/stock_move_line.py#L193-L196 The idea behind this override was that you could provide the package type id via scans and hence that is was not necessary. However, if you click directly on the put in pack button, the wizard still make sense and should therefore be displayed under the same conditions. opw-6325092 Forward-Port-Of: odoo/enterprise#122308
This fixes an error that could occur when workers proposed adding a step from the Shop Floor for manufacturing orders with very similar operations. The change helps ensure improvement suggestions can be submitted reliably in Product Lifecycle Management workflows.
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
Guatemalan credit notes now reference the original invoice’s actual issue date instead of a technical processing timestamp. This helps prevent tax authority rejections and keeps electronic documents aligned with SAT validation requirements.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409 Forward-Port-Of: odoo/enterprise#124794
Deleting a quality check in the middle of a manufacturing work order now keeps the remaining checks connected. This prevents later quality checks from disappearing from the shop floor, helping operators complete all required inspections.
Original PR description
Steps to reproduce the bug: - Create a BOM for product P1 with one work order WO1 - Create 3 quality points linked to WO1 via the `operation_id` field - Confirm a manufacturing order for P1: - 3…
Steps to reproduce the bug:
- Create a BOM for product P1 with one work order WO1
- Create 3 quality points linked to WO1 via the `operation_id` field
- Confirm a manufacturing order for P1:
- 3 quality checks A → B → C are generated
- Open the shop floor for the work order:
- Observe that all 3 quality checks are displayed
- Delete quality check B (the middle one)
- come back to the shop floor for the work order:
- Observe that quality check C is no longer displayed in the shop floor
Problem:
After deleting check B, check C disappeared from the shop floor. Quality checks are stored as a doubly-linked list via the `next_check_id` and `previous_check_id` fields on `quality.check`. The shop floor JS (`mrp_display_record.js`) traverses this list starting from the check with no `previous_check_id`, then follows `next_check_id` until the chain ends. When check B was deleted, it nullified the FK references pointing to it, leaving check A with `next_check_id = False` and check C with `previous_check_id = False`. The traversal from A therefore stopped immediately, and C was never reached.
No `unlink` override existed on `quality.check` to repair the chain before deletion.
Solution:
Added an `unlink` override that, before deleting each check, reconnects its predecessor and successor: if the deleted check has both a previous and a next, `prev.next_check_id` is set to `next` and `next.previous_check_id` is set to `prev`, preserving a valid chain for the remaining checks.
opw-6369298
Forward-Port-Of: odoo/enterprise#124118Malaysia Statement of Account reports now calculate total and overdue amounts using the selected statement date. This ensures the PDF totals match the displayed balance lines, improving accuracy for past-date customer account reporting.
Original PR description
## Current behavior: In Malaysia's Statement of Account, the total and total overdue amounts dont consider the selected Statement Date, and will calculate all the balances up until today in the…
## Current behavior: In Malaysia's Statement of Account, the total and total overdue amounts dont consider the selected Statement Date, and will calculate all the balances up until today in the generated PDF report ## Expected behavior: The total and total overdue amounts should only sum the balances included in the report up until the selected Statement Date ## Steps to reproduce: 1. Install l10n_my_reports module, switch to Malaysian company 2. Go inside Invoicing > Report > Aged receivable 3. Select a specific date in the past 4. Observe that the total amounts dont match with the balance column, and wont change regardless of the date selected ## Cause of the issue: The template used o.total_overdue which ignores the report domain and statement date ## Fix: Accumulate overdue_total in the template loop with the same domain and date_to cutoff as the balance lines, so it always matches the displayed Balance lines for the selected Statement Date opw-6332970 Forward-Port-Of: odoo/enterprise#123694
The US payroll localization now installs through the standard automatic installation process instead of a later setup hook. This prevents upgrade timing issues where payroll localization modules could be treated as not installed until payroll finished loading.
Original PR description
In a [previous PR], a test was introduced to reject any `l10n_xx_hr_*` module that has a `countries` key in its manifest and depends on a module that also has that country key. This test was too…
In a [previous PR], a test was introduced to reject any `l10n_xx_hr_*` module that has a `countries` key in its manifest and depends on a module that also has that country key. This test was too broad and rejected some valid cases: 1. A non-auto-install module can have a country key defined to add flags in the apps kanban view. ([src]) 2. A module that has a country-specific regular dependency, but not as an auto-install condition. The second case is illustrated by [l10n_us_hr_payroll], which should auto-install when `hr_payroll` is installed and a US company exists. With the old test, achieving this required adding `l10n_us` to its auto-install dependencies. But, since `l10n_us` is not auto-installable, `l10n_us_hr_payroll` would not be installed if you create a DB with a US company and only install `hr_payroll`. In practice, that module was still being installed via a [post-init hook] in `hr_payroll`. This hook was installing all `l10n_XX_hr_payroll` modules for each country where a company is located, which is the behavior of the `countries` parameter in the manifest. This caused issues during upgrades as this runs late in the process: after the auto-discovery phase. Modules installed by this hook would be considered as `uninstalled` until `hr_payroll` is loaded. This commit narrows the check to only fail if: - A module has a `country` key in its manifest, and - It has a country-specific module in its **auto-install** dependencies. Moreover, it modifies `l10n_us_hr_payroll` to correctly rely on the auto_install mechanism instead of the post-init hook. [previous PR]: https://github.com/odoo/enterprise/pull/101843 [src]: https://github.com/odoo/odoo/blob/6df9f92a537aa4bb4ee5dc946fe31c4e56e6dfea/odoo/addons/base/models/ir_module.py#L271-L273 [l10n_us_hr_payroll]: https://github.com/odoo/enterprise/blob/24a33ffb769557be498d61328522bb77f68d3a5a/l10n_us_hr_payroll/__manifest__.py [post-init hook]: https://github.com/odoo/enterprise/blob/85185595cfd1ee5310ceb9dc80c0589accad2f19/hr_payroll/__init__.py#L21
The scheduled payroll data update for Australian payroll now restores required salary rule category data before updating salary rules. This prevents an error when users have deleted payroll rule categories, keeping routine payroll maintenance actions running reliably.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716
4 changes
Resolved issues and error corrections
This fixes a display issue where Mexican CFDI invoice fields could disappear when Colombian e-invoicing was also installed. The fields are now placed in a stable invoice header area, so Mexican users can reliably see the CFDI Origen information.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
Ecuador branch users can now create customer invoices without being blocked by an access error. The change avoids requiring access to the parent company when checking country information, keeping normal invoicing flows working in branch setups.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This fixes FedEx label generation so outbound shipments are no longer incorrectly treated as return shipments when return labels are enabled. Businesses using FedEx returns should now see the expected reference information on original shipment labels, improving traceability and reducing label confusion.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
A recent change could prevent some customers from sending payment follow-up reports when their database did not include a specific optional follow-up setting. This update makes that setting apply only where the related feature is installed, restoring follow-up report sending for affected users.
Original PR description
https://github.com/odoo/enterprise/commit/65008de60589fbda924041e35bb34e33d84eb13d introduced a filter based on the `no_followup` field that is not present in every databases, since it was introduced in stable alongside with the `account_no_followup` module. This lead to an AttributeError when trying to send the followup report. This commit adds helpers to be able to use this field only in account_no_followup opw-6310602 Forward-Port-Of: odoo/enterprise#125148
7 changes
Resolved issues and error corrections
This fixes an issue where Mexican CFDI invoice fields could disappear when Colombian e-invoicing was also installed. The fields are now placed in the correct invoice header area consistently, so users can see and manage them regardless of other localization modules.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
This fixes an error that could prevent users from opening the full Employees list when document counts were shown in a multi-company setup. Employee document counts are now calculated separately per relevant company setting, so HR teams can view employee records without interruptions.
Original PR description
Steps to reproduce: ------------------- 1. Install `documents_hr` and `web_studio` with demo data. 2. Add `document_count` to the Employees list view via Studio. 3. Create a second company with an…
Steps to reproduce:
-------------------
1. Install `documents_hr` and `web_studio` with demo data.
2. Add `document_count` to the Employees list view via Studio.
3. Create a second company with an employee, enable multi-company.
4. Open Employees list, click **All** in the search panel.
Issues:
------
Issue 1:
```python
File "/home/odoo/odoo/enterprise/documents_hr/models/hr_employee.py", line 25, in _compute_document_count
if not self.company_id.documents_hr_settings:
File "/home/odoo/odoo/community/odoo/orm/fields.py", line 1429, in __get__
record.ensure_one()
File "/home/odoo/odoo/community/odoo/orm/models.py", line 5640, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.company(1, 2)
```
Issue 2:
```python
File "/home/odoo/odoo/enterprise/documents_hr/models/hr_employee.py", line 31, in _compute_document_count
('partner_id', '=', self.work_contact_id.id)
File "/home/odoo/odoo/community/odoo/orm/fields_misc.py", line 117, in __get__
raise ValueError("Expected singleton: %s" % record)
ValueError: Expected singleton: res.partner(9, 8, 7)
```
Cause:
---------
https://github.com/odoo/enterprise/blob/38674448e387159d28f98c1678856fcaf5f7f52e/documents_hr/models/hr_employee.py#L23-L48
1. The document count computation assumes all employees belong to the same company by directly accessing `self.company_id.documents_hr_settings`. In a multi-company environment, `self` may contain employees from different companies, making self.company_id a multi-recordset and triggering a singleton error.
2. Similarly, when `documents_hr_settings` is disabled, the fallback computation accesses `self.work_contact_id` on a multi-recordset, causing another singleton error.
Solution:
-----------
Split the employees based on whether `documents_hr_settings` is enabled and compute each group separately.
Additionally, use the current employee's `work_contact_id` in the fallback computation to avoid singleton error.
**NOTE:**
This has been resolved from saas-19.4 onward with this improvement [commit](https://github.com/odoo/enterprise/commit/d018d8205300b434728129e199ae048cefbaa296).
opw-6351141The bank reconciliation report now includes all unreconciled transactions up to the selected date, not just those from the latest statement. This helps accountants get a complete view of pending bank items and avoid missing older transactions during reconciliation.
Original PR description
The reconciliation report lists only the unreconciled transactions from the last statement instead of all of them Steps: - Create 4 statements with one statement line each with different dates - Go to the reconciliation report (via the three dot menu on bank journal kanban card) - select date as Today -> only the line from the last statement is displayed opw-6250370 Forward-Port-Of: odoo/enterprise#124635 Forward-Port-Of: odoo/enterprise#119386
This fixes FedEx shipping labels so regular outbound shipments are no longer treated as courtesy returns when return labels are enabled. As a result, the expected reference field appears correctly on the original shipment label, improving label accuracy for warehouse and shipping teams.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
Branch users in Ecuadorian companies can now create customer invoices without being blocked by an access error. This keeps normal invoicing workflows working in parent-and-branch company setups while preserving company access rules.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
Ri.Ba. batch payments can now be validated when the company bank account uses a valid San Marino IBAN. This prevents payment file generation from failing for San Marino accounts and keeps the exported records in the required format.
Original PR description
**_Steps to reproduce :_** - Install l10n_it_riba. - Configure a company with a San Marino (SM) IBAN as the bank account for the journal used for Ri.Ba. - Create a customer payment and add it to a…
**_Steps to reproduce :_** - Install l10n_it_riba. - Configure a company with a San Marino (SM) IBAN as the bank account for the journal used for Ri.Ba. - Create a customer payment and add it to a Batch Payment using the Ri.Ba. payment method. - Validate the Batch Payment. **_Observed behavior :_** The validation fails with the error: `Only bank accounts with an Italian IBAN are allowed to use Ri.Ba. payments` **_Cause :_** The Ri.Ba. validation logic only accepts IBANs with the IT country code and incorrectly rejects valid San Marino (SM) IBANs. **_Fix :_** - Update the Ri.Ba. IBAN validation to accept both Italian (IT) and San Marino (SM) IBANs when generating Ri.Ba. payment files. - While validating Batch Payments for SM IBANs, we observed that the extracted value could overlap with the branch code portion, causing the generated RIBA record to exceed the expected 120-character length. This change updates the extraction logic to prevent overlap and ensure compliance with the required record format. **_opw_** - 6303820 Forward-Port-Of: odoo/enterprise#121439
Fixed an issue that could prevent customer follow-up reports from being sent in databases that do not include the optional no-follow-up setting. The report process now only uses that setting when the related module is available, improving reliability for affected accounting teams.
Original PR description
https://github.com/odoo/enterprise/commit/65008de60589fbda924041e35bb34e33d84eb13d introduced a filter based on the `no_followup` field that is not present in every databases, since it was introduced in stable alongside with the `account_no_followup` module. This lead to an AttributeError when trying to send the followup report. This commit adds helpers to be able to use this field only in account_no_followup opw-6310602 Forward-Port-Of: odoo/enterprise#125148
7 changes
Resolved issues and error corrections
This fixes an issue where employees could not defer a new time off request if an earlier deferred absence had already affected the same payroll period. Payroll teams can now correctly carry time off into the next month without being blocked by an incorrect missing work entry message.
Original PR description
# How to reproduce For an employee with full attendances for april and may: - Create payslip for the month of April, Compute Sheet & Confirm - Create a Time off request for that employee ffrom the…
# How to reproduce For an employee with full attendances for april and may: - Create payslip for the month of April, Compute Sheet & Confirm - Create a Time off request for that employee ffrom the 1st of April to the 10th of April, Approve & Validate > Since the April payroll is closed, you need to defer the Time Off - Report to Next Month - Create payslip for the month of May > The deffered time off should be there - Compute Sheet & Confirm - Create a Time off request for that employee for the 3rd of May, Approve & Validate > Again, the May payroll is closed, so you need to defer the Time Off # The issue You cannot defer the time off because "There is no work entries linked to this time off to report" # The cause When deferring a time off, we call `action_report_to_next_month` that will look for work entries generated during the leave period to defer : https://github.com/odoo/enterprise/blob/f93882555864a1f0a2a3e3863780096c78923bfa/hr_payroll_holidays/models/hr_leave.py#L94-L101 The issue is that, since [this commit], we search for work entries that are not leaves and the first deferring we did transformed the work entries at the start of may into leaves. [this commit]: https://github.com/odoo/enterprise/commit/13ce65b8ca61f9a825f2876e2727cddfae83f894 opw-6318809
This fixes FedEx label generation so regular outbound shipments are not incorrectly treated as return shipments when return labels are enabled. As a result, the shipment reference field appears correctly on outbound labels, improving label accuracy for shipping operations.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
Changing a payslip to a type that does not use worked day lines now correctly clears old worked day information, avoiding misleading payroll data. Belgian payroll reporting was also adjusted so off-cycle payslips without worked days are still counted correctly for remuneration reporting.
Original PR description
hr_payroll: Previously, changing to a structure with `use_worked_day_lines = False` (e.g., 13th month) caused `valid_slips` to be empty and return early, leaving stale worked day lines on the payslip. This commit resets the worked_days_lines before filtering for valid payslips. l10n_be_hr_payroll: After fixing the payroll bug and clearing worked_days_lines correctly, the DMFA report fails to correctly consider remunerations since the off-cycle payslips do not have worked_days_lines anymore. This commit backports a fix from odoo/enterprise#106689 to not skip remunerations for payslips with no worked days lines. task-6401942
This fix prevents payroll salary rule account settings from being reset when installing other apps such as Point of Sale. Businesses that customized payroll accounting, especially in Swiss localization setups, keep their manual configuration intact instead of having it overwritten by default values.
Original PR description
### Steps to reproduce: - In a database with Switzerland localization, install 'Accounting' and 'Payroll' - Manually change the debit and credit accounts on the Swiss ELM salary rules (rule code…
### Steps to reproduce: - In a database with Switzerland localization, install 'Accounting' and 'Payroll' - Manually change the debit and credit accounts on the Swiss ELM salary rules (rule code 1000) - Install 'POS' - Check the accounts you configured on the salary rules >The accounts are reset to their default values ### Cause of Issue: POS depends on the module `stock_account`. When `stock_account` is installed, the `_configure_journals` method in its `__init__.py` creates a new `account.journal` for inventory valuation. To apply default values to this journal, the method retrieves data from the chart template. https://github.com/odoo/odoo/blob/7d16ef88784e18e885b97dbded3231775f1349d2/addons/stock_account/__init__.py#L41 The `hr_payroll_account` module overrides `_post_load_data` and unconditionally calls `_load_payroll_accounts(template_code, company)`. https://github.com/odoo/enterprise/blob/fcf06997a0eb999af86e4b6917311a86f04a390e/hr_payroll_account/models/account_chart_template.py#L16-L18 This triggers the reinstallation of the default payroll accounts, which overwrites and discards any manual configuration changes the user has made to their salary rules. ### Fix: Ensure that default payroll accounts are only reset during a genuine chart of accounts loading process, and not during localized post-load operations triggered by other modules. opw-6251112
Users can now duplicate several maintenance requests at once without the system showing an error. This removes a workflow interruption for teams managing maintenance activities in list view.
Original PR description
Currently, when a user attempts to duplicate multiple maintenance requests simultaneously, the system throws a ValueError (Expected singleton). This PR fixes that. ### How to reproduce the issue: - Install `mrp_maintenance` module; - Open maintenance request list view; - Select multiple records and try to duplicate them using the Action button; - It will throw a traceback stating a singleton error. ### Expected behavior after PR is merged: Now multiple maintenance requests will be copied without raising any errors.
This fix prevents manufacturing orders from disappearing from the shop floor or barcode workflows when required lot numbers for manually consumed components are missing or newly scanned. Users can now see the validation issue and correct it instead of losing access to the order after an error.
Original PR description
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will…
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will disappear when it's gone it will throw a user error, without the MO reappearing. Steps to reproduce --------------------------- **Issue 1** 1) Create a product "final" 2) Create a product "component" tracked by lot 3) Update the on hand quantity and don't assign a lot number 4) Create a BoM for "final" with "component" as component and manual consumption 5) Create a MO and confirm it 6) Go to shopfloor 7) Set "final" quantity 8) Set "component" quantity 10) Close the MO -> The MO disappear (leaving a user error) -> Since the "component" does not have a lot number it should not disappear **Issue 2** Same steps as Issue 1 until step 6: 6*) Add "comp" as barcode to the product component 7*) Go to barcode 8*) Open the manufacturing order 9*) Add the quantity to final 10*) Scan "comp" 11*) Scan a non-existent lot number, ex: "12345" -> It raise the error Observation ---------------------- **Issue 1** When clicking on "Closing production" it will call [onClickValidateButton](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L481-L482)() that will lead us to validate, and validate will [call](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L511) the function [pre_button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L507) in python. in pre_button_mark_done, we will skip any check on the lot number, since we already have set qty_producing (when setting "final" quantity), it will avoid _set_quantities where a check for lot number is made: https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2235-L2239 https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2839-L2844 And it will also skip the consumption wizard since it doesn't check for lot number nor allow to set lot numbers: https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/mrp/models/mrp_production.py#L1658-L1660 After avoiding both checks we go back to validate. In validate and we update the variable underValidation which will [trigger the fadeout animation](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L154) When the [animation ends](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L662-L665), the call to realValidation will be triggered and will call productionValidation that will send a call to [button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L551) In button_mark_done, when calling _action_done on the move_lines, we will finally check that there is a lot number, which will trigger an error : https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/stock/models/stock_move_line.py#L664-L669 but because the fadeout animation is already over, the mo will have disappeared, which means we can't correct the userError that has been raised. **Issue 2** In barcode when scanning a lot after a product, it will not create a lot but only apply a lot_name : https://github.com/odoo/enterprise/blob/7b57a2927aeb8abf84d0f6acc64a7e9bbc8f608d/stock_barcode/static/src/models/barcode_model.js#L1306-L1311 this cause an issue with the existing condition since it only pass the check if there is a lot, but in this case there only is a lot_name. When we click on "Produce" in a Mo in barcode, it will call validate, that in this case, will call button_mark_done: https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/components/main.xml#L163 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/models/barcode_model.js#L602-L605 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L14 opw-6060310
Appointment cancellation emails are now sent in the language of the person who booked the appointment, matching the behavior of confirmation emails. This prevents customers from receiving cancellation notices in the staff member's language and improves clarity for multilingual customers.
Original PR description
**Problem:** When an appointment is cancelled, the cancellation email is always sent in the organizer's (staff member's) language, ignoring the booking customer's language. The booking confirmation,…
**Problem:**
When an appointment is cancelled, the cancellation email is always sent in the organizer's (staff member's) language, ignoring the booking customer's language. The booking confirmation, by contrast, is correctly localized.
**Steps to reproduce:**
1. Set a contact's language to a non-default one (e.g. Romanian).
2. Book an appointment for that contact (they are the booker/attendee).
3. Cancel the appointment.
4. The customer received the confirmation in Romanian but the cancellation email arrives in English.
**Current behavior:**
The cancellation email is rendered in the organizer's language.
**Expected behavior:**
The cancellation email is rendered in the booking customer's language, like the confirmation/invitation email.
**Cause of the issue:**
The cancellation uses `appointment_canceled_mail_template`, whose `lang` is `{{ object.partner_id.lang }}`. On `calendar.event`, `partner_id` is `related='user_id.partner_id'`, i.e. the organizer, not the customer. The template is posted once per event (via `_track_template`), so its single rendering language applies to every recipient, including attendees whose own language differs. The confirmation email is unaffected because it is the per-attendee `attendee_invitation_mail_template` (model `calendar.attendee`), rendered once per attendee in that attendee's language.
**Fix:**
Deriving the language from `appointment_booker_id` makes the cancellation consistent with the other appointment mails, which are meant for the person who booked the meeting. It falls back to `partner_id` when there is no booker (e.g. an event not created through the appointment flow), preserving the previous behavior in that case.
opw-63231793 changes
Resolved issues and error corrections
Fixed an issue where FedEx outbound shipping labels could lose their reference field when return labels were enabled. This helps businesses keep shipment labels accurate while still supporting return label creation.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
The Timesheets overtime indicator now respects the selected time entry unit even when users switch to another language. This prevents employees and managers from seeing remaining time unexpectedly change from days back to hours due to translated labels.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133
This fix standardizes the XML encoding label used in SEPA and ISO 20022 payment files to uppercase. It helps avoid warnings or rejections from stricter banking providers, such as SIX in Switzerland, without changing payment workflows.
Original PR description
The W3C recommendations for XML state that the encoding defined for an XML document should not be case-sensitive. However, some banking providers (SIX for Switzerland) are stricter and may throw warnings or errors if upper-case is not used. https://www.w3.org/TR/2008/REC-xml-20081126/#NT-EncodingDecl opw-4948708