Friday, September 4, 2026
31 changes · saas-19.4
Resolved issues and error corrections
This fixes the Mexican accounting setup so accumulated depreciation and amortization accounts are classified correctly. Businesses using fixed assets such as vehicles will now see depreciation amounts computed and reflected properly in journal entries and asset balances.
Original PR description
Issue: When creating an asset using an "154.01.01 Vehicles", the depreciation values of the journal entries created are zero Steps to reproduce: 1. Install l10n_mx and enter a Mexican company 2.…
Issue: When creating an asset using an "154.01.01 Vehicles", the depreciation values of the journal entries created are zero Steps to reproduce: 1. Install l10n_mx and enter a Mexican company 2. Create an asset and setting the fixed asset account as 154.01.01 Vehicles 3. Click on "Compute Depreciation" and in the "Depreciation Board" page, all the journal entries created will not have any depreciation values Cause: In the l10n_mx chart of accounts, all accumulated depreciation accounts are set as "expense_depreciation" whereas they should be asset accounts because accumulated depreciation accounts are used to credit asset accounts to decrease asset values. If an account of type "expense_depreciation" is used, then when the depreciation account is credited and the expense account is debited, all financial events will occur within expense accounts, which is why no depreciation values were recorded as the asset balances stay the same. Additionally, the "asset_depreciation_account_id" field on "account.account" has a domain restricting selection to "account_type" of "asset_fixed" or "asset_non_current" Solution: Change the "account_type" of l10n_mx accumulated depreciation accounts from "expense_depreciation" to "asset_fixed" and l10n_mx accumulated amortization accounts from "expense_depreciation" to "asset_non_current" Updrade PR: [odoo/upgrade/pull#10936](https://github.com/odoo/upgrade/pull/10936) opw-6359618 Forward-Port-Of: odoo/odoo#284309 Forward-Port-Of: odoo/odoo#278185
This update fixes several issues in the stock allocation report, including incorrect allocation quantities, mobile display problems, label printing layout, and repeated-click errors. It also makes allocation easier to use from forecast reports and stops the report from opening automatically during operation validation, reducing interruptions for warehouse users.
Original PR description
This PR fixes issues with [the recently merged](https://github.com/odoo/odoo/pull/264299) allocation report. Main changes are: - Add specific design for mobile device; - Don't allocate already reserved quantity; - Allocation report won't open itself automatically when validating an operation from the Barcode app, no matter the configuration (a setting is planned to be added in `master` to let the possibility if the user wants); - Add the possibility to allocate from the forecast report. For more details on these changes or other fixes, check the corresponding commit's message. _________ **Enterprise PR:** odoo/enterprise#122258 task-4894566
This fix prevents Italian electronic invoices from listing unrelated down payment documents when generating linked invoice details. It helps ensure credit notes and final invoices reference only the relevant prior document, reducing confusion and improving compliance data accuracy.
Original PR description
Steps to reproduce: - Create a sale order with a down payment term. - Invoice the down payment (down payment invoice A). - Credit that down payment invoice directly (credit note A), without…
Steps to reproduce: - Create a sale order with a down payment term. - Invoice the down payment (down payment invoice A). - Credit that down payment invoice directly (credit note A), without reconciling it with anything else. - Generate the FatturaPA XML for credit note A. - Observe that DatiFattureCollegate lists both down payment invoice A and credit note A itself, instead of only down payment invoice A. On an order with several down payment invoices/credit notes over time, every one of them is listed instead of just the document the current credit note actually reverses. Cause of the issue: _l10n_it_edi_export_data built downpayment_moves from self.invoice_line_ids._get_downpayment_lines().move_id with no filtering. _get_downpayment_lines() (sale override) returns every invoice line ever created against the same down payment sale order line, across the whole life of the order, not just the invoice the current document actually relates to. The template renders DatiFattureCollegate for every one of those moves unconditionally, on top of the already-correct reversed_entry_id/reconciled_moves fallback, including the current document itself. Solution: Restrict downpayment_moves to lines with a negative price_subtotal, mirroring the existing down payment deduction-line detection a few lines above, and explicitly exclude the current document. This limits DatiFattureCollegate's down payment entries to the case they are meant for: a final invoice actually deducting a previously invoiced down payment. opw-6429716 Forward-Port-Of: odoo/odoo#285555 Forward-Port-Of: odoo/odoo#279938
The barcode workflow now prints labels for the allocated products instead of printing the related operation report. This prevents warehouse users from receiving the wrong printout and adds a clearer way to view allocation details when needed.
Original PR description
Before this commit, the print button on barcode line printed the allocated operation's report instead of the allocated products' labels. This commit fixes that. _________________ **Community PR**: odoo/odoo#272722 [task-4894566](https://www.odoo.com/odoo/966/tasks/4894566)
Downloading spreadsheets as Excel files now works when they contain inserted images. The export process uses the same authorized image access as the web interface, preventing failed downloads for users.
Original PR description
Since https://github.com/odoo/enterprise/pull/97488, the images are shared across spreadsheets and the attachments are no longer related to a specific record. Due to the management of the…
Since https://github.com/odoo/enterprise/pull/97488, the images are shared across spreadsheets and the attachments are no longer related to a specific record. Due to the management of the IrAttachment access rights, it means that those attachments are not accessible by anyone by default and we rely on the access_token to display them in the webclient. However, the method that builds the final xlsx file fetches the images from the server and did not use the access token, meaning that it could never access the attachment. Such situation raised a UserError that was caught by the webclient. How to reproduce: - As admin, create a spreadsheet and insert an image inside of it - try to download the spreadsheet as an xlsx file counterpart of https://github.com/odoo/enterprise/pull/126384 Task-6432724 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285981 Forward-Port-Of: odoo/odoo#279788
When a contact with multiple linked active users is mentioned, all of those users now receive the notification immediately instead of only seeing it after reloading. Related performance test expectations were updated to reflect the extra work needed to notify everyone correctly.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This commit raises the query counts of the activity tests: the fix in odoo resolves each notified partner to its active users, which costs one query per post with an inbox recipient. https://github.com/odoo/odoo/pull/283836 Forward-Port-Of: odoo/enterprise#129969
When a contact with multiple user accounts is mentioned, all active linked users now receive the live notification immediately. This prevents some users from missing mention alerts until they reload the page, improving reliability of team communication.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This happens because the notification is sent on the single user that _notify_get_recipients picks for a partner, and since "[REF] bus, mail: use user rather than partner as bus target" a user is its own bus channel, so the other users of that partner are no longer reached. The notification record is stored per partner, which is why a reload shows it. This commit fixes the issue by sending to every active user of the notified partner. https://github.com/odoo/enterprise/pull/129969 Forward-Port-Of: odoo/odoo#283836
DHL shipping in Odoo no longer automatically requests a carrier pick-up when creating shipments. This avoids extra scheduling steps and DHL errors when pick-up windows are not configured, making DHL behave more like other shipping carriers.
Original PR description
Before this commit, the DHL REST module had the pick-up request set, which led to an unnatural use flow, needing to set up an scheduled date for pick-up, and several errors from DHL when these were not properly configured. This feature was unique to this module among the shipping carriers as we don't normally request pick-up for packages and leave it to user to decide how to do it. This commit removes the request for pick up and the logic that was needed to make it work. This will make the behavior consistent with other carriers in Odoo, and avoids the need to set scheduled pick-up windows and having to deal with unnecessary errors. opw-6148927 Forward-Port-Of: odoo/enterprise#123773
Employees in Belgium can now combine a company car with public transport or bicycle commuting without those options being automatically removed. This ensures all eligible transport reimbursements are correctly included in payroll calculations.
Original PR description
When configuring transport modes on an employee contract version profile, selecting a company car automatically reset public transport (bus, tram, metro) kilometers to zero and disabled the bicycle option. This prevented employees who use multiple transport modes (e.g., combining a company car with public transport or a company bicycle) from having multiple transportation reimbursements calculated on their payslip. Remove the automatic field resets for public transport and bicycle options in `_onchange_transport_mode` and remove `_onchange_has_bicycle`, allowing these transport modes to co-exist with a company car. task-6514557 Forward-Port-Of: odoo/enterprise#129972
Fixes an issue where event visitors could see outdated booth options after switching booth categories. This prevents confusion during booth registration and helps the event booth booking flow complete reliably without requiring a page reload.
Original PR description
Before this commit, the "Get A Booth" page of an event could keep listing the booths of the category checked on load after the visitor picks another one. Only a page reload brought the right ones…
Before this commit, the "Get A Booth" page of an event could keep listing the booths of the category checked on load after the visitor picks another one. Only a page reload brought the right ones back. The tour webooth_exhibitor_register timed out on that list: FAILED: [5/13] Tour webooth_exhibitor_register -> Step Choose Booth (trigger: .o_wbooth_booths div:contains(OpenWood Demonstrator 2) input:not(:visible)). TIMEOUT step failed to complete within 10000 ms. This happens because the page fetches the booths of the category checked on load, and clicking another category fetches its booths while that first answer is still on its way. The answer coming back last fills the list, and the widget caches it under the category active on arrival, so the booths of the first category land in the cache of the clicked one. This commit fixes the issue by caching an answer under the category it was asked for, and by filling the list only while that category is still the chosen one. https://runbot.odoo.com/odoo/error/110527 https://runbot.odoo.com/odoo/error/161834 Forward-Port-Of: odoo/odoo#286552 Forward-Port-Of: odoo/odoo#286266
This fix ensures French VAT credits from a previous period are included in the next tax closing journal entry. It helps companies keep tax returns compliant with French accounting requirements and prevents missing carryover amounts in accounting records.
Original PR description
### Issue before this commit: When generating a tax closing entry for France, the VAT credit carryover from the previous period is missing from the journal entry lines. ### Steps to reproduce the…
### Issue before this commit: When generating a tax closing entry for France, the VAT credit carryover from the previous period is missing from the journal entry lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_fr 2. Go to Vendor > Bills 3. Create a vendor bill with date in June and price > 0 (ex. 1000$) and the 20% G tax that produce a 200$ VAT tax 4. Go to Customers > Invoices 5. Create an invoice with price > 0 (ex. 9000$), the date in July and the 20% G tax that will produce a 1800$ VAT tax 6. Go to Tax Return and validate all opened months up to July and see that for June the balance is -200$ 9. Then go to View Entries of July using the 3 dots next to the "submit" button and see that there is no mentioning of the 200$ carry over of credit from the month before ### Cause of the issue: The issue stems from a structural change in the core code where the logic to evaluate and balance the tax receivable account was removed from the _add_tax_group_closing_items method. Consequently, the VAT closing entry now only processes the current period's taxes and there is no reporting of any carried-forward VAT credits. ### Reason to introduce the fix: French accounting rules strictly require the carried-forward VAT credit to be explicitly integrated into the current period's tax closing entry. opw-6438648 Forward-Port-Of: odoo/enterprise#130377 Forward-Port-Of: odoo/enterprise#129181
The GSTR-2B return workflow now shows the correct option to fetch GSTR-2B data instead of an irrelevant Submit button. This restores the intended process and prevents reconciliation from being blocked after recent tax return changes.
Original PR description
On GSTR-2B returns, do not show the 'Submit' button instead show the 'Fetch GSTR-2B' button once all the checks pass. Clicking it fetches the GSTR-2B data. After the recent tax returns refactor (https://github.com/odoo-dev/enterprise/commit/603443c5a45609145de8be288eadc9e06e63e1f3), GSTR-2B returns wrongly showed a 'Submit' button that is not part of their flow, and there was no longer any way to move the return forward and fetch its GSTR-2B data, blocking the reconciliation. task-6529017
The UK CIS report now correctly includes payment information for receipts that have CIS tax applied. This ensures businesses get a more complete and accurate view of CIS-related supplier activity, not just vendor bills.
Original PR description
With the l10n_uk_reports_cis module installed: - Create a vendor bills and add a CIS tax --> This vendor's bills appear correctly in the report. - Create a receipt and add a CIS tax --> This type of bill appears in the report, but the payment is not showing up. opw-6282548 Forward-Port-Of: odoo/enterprise#129395 Forward-Port-Of: odoo/enterprise#124043
Electronic invoice imports no longer fail when an invoice line has a 100% discount together with tax included in the price. This prevents import errors for valid supplier/customer documents and improves reliability of accounting workflows.
Original PR description
Due to the following commit: 01efd8cfcce3269ca6b88d549a670b08a90298cb, a division by zero error is raised when a 100% discount is used with a price-included tax. When the discount is 100%, it is impossible to retrieve the original tax amount before discount using a simple multiplication as the current raw_tax_amount_currency is zero. In that case, we need to recompute taxes using the original unit price before discount. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282430
Planning managers who do not have HR permissions can now publish scheduled slots successfully. The system uses accessible employee information where possible so employees still receive their planning notifications.
Original PR description
Steps: - As a planning manager without HR right - Schedule planning slots - Publish them Actual result: - employee_ids is empty as user don't have access HR - nothing is sent Expected result: - Planning publication is well sent Similar to: https://github.com/odoo/enterprise/pull/127503 Forward-Port-Of: odoo/enterprise#130298
Website building blocks now display with better contrast when a dark color palette is selected, making previews and placed content easier to read. This also speeds up the snippet picker by reusing prepared dark preview versions instead of recalculating them each time.
Original PR description
Fix some snippets in dark palettes task-6485048
Fixed an issue where creating or editing technical views could fail even when the chosen model and view layout were valid. The system now applies the selected model before validating the view, preventing false validation errors and making view setup more reliable.
Original PR description
**Problem:** Creating a view from Settings > Technical > User Interface > Views fails with a validation error, even though both the model and the architecture are valid. **Steps to reproduce:** 1. Go…
**Problem:**
Creating a view from Settings > Technical > User Interface > Views fails with a validation error, even though both the model and the architecture are valid.
**Steps to reproduce:**
1. Go to Settings > Technical > User Interface > Views
2. Click New
3. Set the View Name and pick a model in "Model of the view"
4. Set the View Architecture to `<list><field name="name"/></list>`
5. Save
**Current behavior:**
The record cannot be saved:
Error while validating view near:
<list __validate__="1"><field name="name"/></list>
Model not found: False
Duplicating an existing view and editing the copy works, so the issue only shows up on brand new records.
**Expected behavior:**
The view is saved, and validated against the model that was picked.
**Cause of the issue:**
The form edits `model_id`, a non-stored `Many2one` whose inverse `_inverse_compute_model_id` is what actually fills the stored `model` field. The architecture is edited through `arch_base`, whose inverse chain ends in `_inverse_arch` writing `arch_db`; `write` then runs `_check_xml`, which validates the architecture against `view.model`.
Both values therefore reach the record through inverse methods, so the order those run in decides whether `model` is set by the time the architecture is validated. That order became deterministic in this version: the ORM sorts inverse groups by `(field.write_sequence, field index)`. Both fields keep the default `write_sequence` of 0, which leaves the declaration order to break the tie, and `arch` is declared well before `model_id` — so the architecture is validated while `model` is still empty.
The same ordering also breaks a plain edit: changing the model and the architecture of an existing view in a single save validates the new architecture against the previous model.
**Fix:**
`write_sequence` is the ORM's hook for exactly this kind of ordering dependency, so a negative one on `model_id` states the real constraint — the model has to be known before anything is validated against it — rather than leaving it to where the fields happen to sit in the class. It also covers the write path, which a create-only workaround would miss.
opw-6467991This fix ensures accounting records correctly flag a numbering gap when a previously posted journal entry is reset to draft and a later entry is posted. This helps businesses keep audit trails and journal sequencing accurate without changing already assigned document numbers.
Original PR description
To reproduce: * create and post 2 journal entries in the same journal * reset to draft the entry with the highest number * create and post a third entry in the same journal The draft entry is not flagged as having made a gap, because at the time of resetting it to draft, it was the last entry and therefore didn't really make a gap. 3 options to solve were considered: * flag all moves when reseting to draft even if they were the last of the chain * if we reset the last move of the sequence to draft, also remove its sequence and put it back to `/` * when posting, check if the previous number was draft. If it was the case, flag it. The last options was taken in this fix to avoid changing the previous behavior while fixing the current issue. Forward-Port-Of: odoo/odoo#286204
Updates the spreadsheet engine and dashboard components to fix several user-facing issues with charts, pivots, printing, dark mode, and mobile display. This improves spreadsheet stability, visual consistency, and usability across devices.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7660254439 [REL] 19.4.11 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7660254439 [REL] 19.4.11 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/a510812a88 [FIX] carousel: cannot add non-existing chart to carousel [Task: 6455790](https://www.odoo.com/odoo/2328/tasks/6455790) https://github.com/odoo/o-spreadsheet/commit/c875c44655 [FIX] Fonts: fix linux font on css variable [Task: 6452045](https://www.odoo.com/odoo/2328/tasks/6452045) https://github.com/odoo/o-spreadsheet/commit/ae830f0ff5 [FIX] svg: remove unused commented SVGs [Task: 6317134](https://www.odoo.com/odoo/2328/tasks/6317134) https://github.com/odoo/o-spreadsheet/commit/6970933bb4 [FIX] chart: fix funnel chart show value [Task: 6475094](https://www.odoo.com/odoo/2328/tasks/6475094) https://github.com/odoo/o-spreadsheet/commit/06d1c65ec7 [FIX] pivot: unbounded ranges in the pivot side panel [Task: 6478220](https://www.odoo.com/odoo/2328/tasks/6478220) https://github.com/odoo/o-spreadsheet/commit/c95922a0d1 [FIX] figure: color of snap lines in dark mode [Task: 6515587](https://www.odoo.com/odoo/2328/tasks/6515587) https://github.com/odoo/o-spreadsheet/commit/95b0854895 [FIX] chart: consistency in the background color for xlsx export [Task: 6507087](https://www.odoo.com/odoo/2328/tasks/6507087) https://github.com/odoo/o-spreadsheet/commit/583393936f [FIX] chart_menu: align chart menu items tag and style [Task: 6469005](https://www.odoo.com/odoo/2328/tasks/6469005) https://github.com/odoo/o-spreadsheet/commit/41874ca9de [FIX] composer: crash when hovering a composer token [Task: 5153319](https://www.odoo.com/odoo/2328/tasks/5153319) https://github.com/odoo/o-spreadsheet/commit/1bedab5196 [FIX] evaluation: wrong dependencies invalidation with spread formulas [Task: 5103328](https://www.odoo.com/odoo/2328/tasks/5103328) https://github.com/odoo/o-spreadsheet/commit/037f4f8aa5 [FIX] print: figure border wrong render [Task: 6458624](https://www.odoo.com/odoo/2328/tasks/6458624) https://github.com/odoo/o-spreadsheet/commit/44c8d0b2a8 [FIX] chart: fix bubble chart show value [Task: 6475014](https://www.odoo.com/odoo/2328/tasks/6475014) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Bills created from employee expenses in Mexico now correctly show their CFDI XML attachments when available. This ensures users can access required tax documents directly in Odoo and supports related SAT validation checks for these receipts.
Original PR description
**Current behavior:** Currently, account moves created from expenses (type receipt) don't include the XML when it is a CFDI. Causing users cannot see their attachment even though it is created on DB. https://docs.google.com/videos/d/1eFSAA-wvUzPDwIJDeiS2dkne94lGM7QBxRfjN3HxaLw/play **Versions:** 19+ **Fix:** Implementing a new helper to identify those moves that can actually hold a CFDI document (for now, all `is_invoice()` documents + vendor bill receipt, `in_receipt`), so now, we include 'in_receipts' in _compute_l10n_mx_edi_cfdi_state_and_attachment, _compute_l10n_mx_edi_document_ids, _compute_l10n_mx_edi_update_sat_needed and l10n_mx_edi_cfdi_try_sat. As these documents might need to fetch SAT services as well. Task-id: [6397080](https://www.odoo.com/odoo/project/49/tasks/6397080) Forward-Port-Of: odoo/enterprise#130045 Forward-Port-Of: odoo/enterprise#126493
The French VAT reporting flow now checks for duplicate XML declarations before sending them to Aspone. This avoids rejected submissions and prevents unnecessary paid service calls.
Original PR description
When sending an xml to aspone, they will check if a duplicate declaration exist, and if it's the case, then they will refuse it. Since contacting aspone cost us money we will block the sending before that. task-6420220 Forward-Port-Of: odoo/enterprise#130406 Forward-Port-Of: odoo/enterprise#127953
Corrects a rounding mismatch that could cause Mexican electronic payment complements for USD invoices paid in MXN to be rejected by the certification provider. This helps businesses successfully validate and send affected CFDI payment documents, especially for partial payments or payments made with exchange-rate differences.
Original PR description
**Steps to reproduce:** * Install the **l10n_mx** localization. * Enable **USD** and fetch the latest currency exchange rate from the settings. * Configure **Quadrum** as the **PAC** in the settings.…
**Steps to reproduce:**
* Install the **l10n_mx** localization.
* Enable **USD** and fetch the latest currency exchange rate from the settings.
* Configure **Quadrum** as the **PAC** in the settings.
* Create and sign a USD invoice with **16% IVA** (e.g. 4,500 USD + 720 USD tax = 5,220 USD total).
* Send the invoice to **CFDI**.
* Register a **partial MXN payment** that does not convert to a round USD amount (e.g. 30,000 MXN = 1,762.45 USD).
* Send the payment complement to the PAC by clicking **Update Payments** on the invoice.
**Observed behavior:**
The PAC rejects the CFDI with error **CRP20268**:
> El campo BaseP que corresponde a Traslado, no es igual a la suma de
> los importes de las bases registrados en los documentos relacionados
> donde el impuesto del documento relacionado sea igual al campo
> ImpuestoP de este elemento y la TasaOCuotaDR del documento
> relacionado sea igual al campo TasaOCuotaP de este elemento.
**Cause:**
* The SAT validator enforces a strict arithmetic relationship between three fields that are printed in the payment complement XML:
```
BaseP == round(BaseDR / EquivalenciaDR, 6)
```
* When `percentage_paid` is a non-terminating decimal (which happens for any partial MXN payment against a USD invoice), the internal `raw_base` float carries more precision than the 6-decimal-place `BaseDR` that is actually written to the XML:
```
percentage_paid = 1762.45 / 5220 = 0.33763409961685825...
raw_base = 4500 × 0.33763... = 1519.353448275862...
BaseDR (XML) = float_round(raw_base, 6) = 1519.353448
```
* The old code then used `raw_base` (the unrounded internal value) as the dividend when computing BaseP:
```
BaseP (old) = float_round(1519.353448275862... / 0.0587483333, 6)
= 25862.068980 ← written to <TrasladoP BaseP="...">
```
* The PAC performs the same division using only what it can read from the XML. The already-rounded BaseDR:
```
BaseP (PAC) = round(1519.353448 / 0.0587483333, 6)
= 25862.068975
```
* The 6th-decimal mismatch (25862.068980 ≠ 25862.068975) triggers CRP20268 and the document is rejected.
* The same issue occurs with a full MXN payment on a different date than the invoice when multiple invoice lines cause the rounded aggregate to diverge from the sum of per-line raw values.
**Fix:**
In `_l10n_mx_edi_add_payment_cfdi_values` (`account_move.py`), the block that builds the BaseP aggregation list was changed from iterating over raw per-`base_line` amounts to building a single synthetic entry per invoice using the already-rounded document-level `BaseDR` values (`tax_details['base']`) as the dividend:
- Before : wrong: raw_base ≠ BaseDR printed in the XML
'raw_base': tax_details['raw_base'] / inv_rate
- After : correct: 'base' == BaseDR, the exact value in the XML
'raw_base': tax_details['base'] / inv_rate
This guarantees that Odoo and the PAC divide the identical value, producing the identical 6-decimal result.
The `base_line_cfdi_values_mx_curr_list` path (used only for the `Totales` summary fields rounded to 2 dp) is left unchanged because the CRP20268 rule does not apply to that block.
opw-6468077
Forward-Port-Of: odoo/enterprise#128357This fixes an online store product page issue where multi-checkbox attribute options could become selected automatically after refreshing the page. Customers now see only the options they intentionally choose, reducing confusion and preventing unintended product configurations.
Original PR description
**Steps to reproduce:** 1. Create a product. 2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio). 3. Publish the product and open its page on eCommerce. 4. Verify that no…
**Steps to reproduce:**
1. Create a product.
2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio).
3. Publish the product and open its page on eCommerce.
4. Verify that no multi-checkbox option is selected by default.
5. Refresh the page twice.
**Issue:**
On the second page refresh, the first option of the multi-checkbox attribute is automatically selected, and the URL is updated with its parameter.
**Cause:**
- `_prepare_product_values` construct attribute combinations by mapping requested `attribute_values` query parameters line by line.
- When URL query parameters were present (e.g., set after the first refresh), the fallback logic `or ptal.product_template_value_ids.filtered('ptav_active')[:1]` treated unselected `multi_checkbox` attribute lines as missing required selections rather than empty selections, forcing them to default to their first active option.
**Fix:**
If no selection is provided for `multi_checkbox` line, return an empty recordset instead of falling back to the first active option.
opw-6494697
Forward-Port-Of: odoo/odoo#286492
Forward-Port-Of: odoo/odoo#284798Fixed an issue where creating a time off request could fail when a leave type counted calendar days and no employee had been selected yet. This prevents an error screen during leave management and keeps the request form usable.
Original PR description
BUG :
- choose a US company
- in sick leave timeoff type , make to count days as "calendar days"
- open management and try to create a leave -> traceback
REASON :
- when you open the timoff form view for the first time , the employee_id in empty this causes work_time_per_day_mapped to be empty, => work_time_per_day_mapped[leave.date_from, leave.date_to, include_public, calendar] this fails because there is no entry in the dict
FIX:
- add a safeguard at line 653 , to prevent the computations when the leave has no employees , in this case we should fall back to the else in line 739, this acts as way to prevent tracebacks, during calculation , because in the database itself you could never have a leave with no employee assigned to it.
task-6411996The website shop editor no longer crashes when users choose the Grid catalog preset in the Products Design panel. This keeps product page customization usable and avoids disruption while editing the online store.
Original PR description
Steps to reproduce: 1. Open the website editor on /shop. 2. Select the products grid and expand Products Page in the sidebar. 3. Click the Design button to open the Products Design sliding panel. 4. Click the 4th preset (Grid catalog) in the Preset picker. Before this pr: - The page crashed with a render loop error. After this pr: - presets can be picked normally, no crash. The preset list was being drawn twice at once, and both copies were registering under the same internal ID. Now each copy gets its ownnsuffixed ID, so they don't clash anymore. Also removed a redundant duplicate t-if on BuilderSelectItem already covered by its parent t-if. Also removed a dead label.translate="Presets" attribute that ProductsDesignPanelPresets never reads. opw-6478531 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Portal users who follow a project can now open the tasks they are allowed to view without seeing an incorrect “not found” message. This makes task access from project links consistent with the task list in the portal, reducing confusion for external users and customers.
Original PR description
Before this commit, the portal user could have a request not found when he wants to access to a task from a project he follows even if he can access to the task in /my/tasks route. This commit makes sure the read access are checked instead of checking if the user can access to the task thanks to the token since the token if the one of the project. Forward-Port-Of: odoo/odoo#285878
Fixed an issue where Belgian payroll could incorrectly pay a public holiday when an employee's guaranteed sick pay period had already ended. The change ensures sickness certificates are checked by local calendar date, so payroll results are accurate when certificates start on the same day as a public holiday.
Original PR description
Steps to reproduce: - Employee on full-time sickness certified month by month (one hr.leave per medical certificate), guaranteed salary period already exhausted. - Compute payroll for the month whose public holiday falls on the first day of a new certificate. - Public holiday work entry stays paid, every other day that month is correctly unpaid. Cause: the 30-day lookback compared exact datetimes instead of calendar dates, so a certificate starting the same day as the holiday but later in clock-time got excluded. Also ignored timezone: date_from is stored in UTC and needs localizing before taking .date(). Fix: compare local calendar dates via hr.leave's own request_date_from/request_date_to instead of raw UTC datetimes. Added a regression test for the split-certificate case. Task 6512860 Forward-Port-Of: odoo/enterprise#129889
This fixes an issue where additional deliveries on an existing sales order could create incorrect or even negative cost entries when average costing is used. Costs are now based on the actual value of stock movements, helping invoices reflect more accurate margins and inventory costs.
Original PR description
## HOW TO REPRODUCE: - Create a product AVCO Perpetual - Receive 10 units with a unit price of $10 => Product average price is now $10 - Create a Sale Order for 10 units, confirm, deliver and invoice…
## HOW TO REPRODUCE:
- Create a product AVCO Perpetual
- Receive 10 units with a unit price of $10 => Product average price is now $10
- Create a Sale Order for 10 units, confirm, deliver and invoice => COGS are at $100
- Receive 1 unit with a price of $5 => Product average price is now $5
- Update SO and add 1 unit, deliver and invoice this new unit => New invoice COGS is $-45
This is because Odoo computes the COGS for the whole SO, and decided that the value of the deliveries is the `quantity * standard_price`, which would means `11 units * $5 = $55`. Because the 1st invoice has a COGS balance of $ 100, the 2nd invoice is set to $ -45.
This behavior is inconsistent with how it was done in previous versions. Furthermore, if we added the +1 unit in a new invoice, the COGS would have been $ 5, for a total products COGS of $ 105.
- - -
With this fix, the COGS are computed using the average of the move value. So if the first move value is $100, and the second is $5, then the global COGS for the sale order should be $105. Because the first invoice COGS are already at $100, the second invoice COGS must be $5.
OPW-6442049
---
## TEST RESULT WITHOUT FIX:
```
2026-08-21 08:00:11,722 28203 INFO oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: Starting TestAngloSaxonValuation.test_cogs_average_multiple_invoices_and_deliveries ...
2026-08-21 08:00:13,055 28203 INFO oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: ======================================================================
2026-08-21 08:00:13,055 28203 ERROR oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: FAIL: TestAngloSaxonValuation.test_cogs_average_multiple_invoices_and_deliveries
Traceback (most recent call last):
File "/home/odoo/Odoo/src/19.0/odoo/addons/sale_stock/tests/test_anglo_saxon_valuation.py", line 1935, in test_cogs_average_multiple_invoices_and_deliveries
self.assertRecordValues((cogs_line_1 | cogs_line_2), [
File "/home/odoo/Odoo/src/19.0/odoo/odoo/tests/common.py", line 727, in assertRecordValues
self.assertSequenceEqual(expected_reformatted, record_reformatted, seq_type=list)
AssertionError: Lists differ: [{'ac[142 chars]it': 5.0}, {'account_id': 3566, 'debit': 5.0, 'credit': 0.0}] != [{'ac[142 chars]it': 45.0}, {'account_id': 3566, 'debit': 45.0, 'credit': 0.0}]
First differing element 2:
{'account_id': 3536, 'debit': 0.0, 'credit': 5.0}
{'account_id': 3536, 'debit': 0.0, 'credit': 45.0}
[{'account_id': 3536, 'credit': 100.0, 'debit': 0.0},
{'account_id': 3566, 'credit': 0.0, 'debit': 100.0},
- {'account_id': 3536, 'credit': 5.0, 'debit': 0.0},
+ {'account_id': 3536, 'credit': 45.0, 'debit': 0.0},
? +
- {'account_id': 3566, 'credit': 0.0, 'debit': 5.0}]
+ {'account_id': 3566, 'credit': 0.0, 'debit': 45.0}]
? +
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283778This update corrects how Adyen payment information is read from incoming payment data. It helps ensure payment transactions use the right values, reducing the risk of failed or incorrectly processed payments.
Original PR description
opw-6512723 Forward-Port-Of: odoo/odoo#286391 Forward-Port-Of: odoo/odoo#284773
Refund payslips are now recalculated accurately whenever worked days or payroll lines are recomputed, not only during a reset. This helps prevent incorrect payroll refund amounts and improves reliability for payroll teams.
Original PR description
Instead of only resetting correctly the refund payslip in the reset, ensure that anytime we recompute worked days or lines, the refund is correctly computed. Forward-Port-Of: odoo/enterprise#129332
This fixes an issue in the HTML editor where pressing Enter in a bullet list item containing a table did not split the bullet correctly. Users can now edit text before or after tables in lists more naturally, without accidentally keeping everything in one bullet or moving content out of the list incorrectly.
Original PR description
### Steps to reproduce: - Insert a bullet list - Inside of the list, insert a table - Write before and/or after the table (in the same list item) - Press enter before and/or after the inserted text - Notice that the bullet is not split like in a normal list ### Root Cause: - On Enter, list plugin checked whether the list item contained unsplittable element. Since the table was inside the list item, it always treated the list item as unsplittable, even when the cursor was outside the table. As a result, the list item could never be split. ### Solution: - Instead of checking the whole list item, walk up from the split target to the list item and look for an unsplittable element along the way. This allows the list item to split normally when the cursor is outside the unsplittable. task-6449843 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286028 Forward-Port-Of: odoo/odoo#280903