Wednesday, September 9, 2026
62 changes · master
Resolved issues and error corrections
This fix ensures invoices sent to ZATCA are properly marked as submitted even when the user only has read-only access to journals. This prevents the same invoice from being sent again accidentally, reducing duplicate submissions and reconciliation issues.
Original PR description
**Steps to reproduce:** This issue is hard to reproduce because it requires a live ZATCA connection: - As a user with read-only permission on journals, send an invoice to ZATCA. - You get an access error on the journal, and the invoice is unchanged (You can try sending it again to ZATCA). **Issue:** What happens is: - A user with read-only permission on journals sends an invoice to ZATCA. - If ZATCA responds with a 200 (successfully submitted), we try to write on the field `journal.l10n_sa_latest_submission_hash` - With no write permissions, the write fails and all changes are rolled back (on odoo, not on ZATCA) - We can send the invoice again to ZATCA, resulting in duplicates. **Solution:** - Added a sudo when writing on the field: `journal.l10n_sa_latest_submission_hash` opw-6320179 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287081 Forward-Port-Of: odoo/odoo#278728
The French simplified profit and loss report now includes all relevant expense lines in the Operating expenses total. This helps companies using the French fiscal declaration avoid understated expense totals and improves accuracy of the 2033 B report.
Original PR description
**Steps to reproduce:** - Install the `l10n_fr_reports` module and switch to the FR Company. - Navigate to Invoicing > Reporting > Fiscal Declaration and select `2033 B`. - Observe the formula of `A…
**Steps to reproduce:** - Install the `l10n_fr_reports` module and switch to the FR Company. - Navigate to Invoicing > Reporting > Fiscal Declaration and select `2033 B`. - Observe the formula of `A - Accounting income` > `Operating expenses (II)`. **Observation:** The formula does not include the balances of `FR_2033_B_c244`, `FR_2033_B_c250`, and `FR_2033_B_c252`. **Root Cause:** At [1], the formula for `Operating expenses (II)` is missing the balances of fields `244, 250, and 252`, even though these lines are part of the operating expenses section. **Fix:** This commit ensures that `Operating expenses (II)` displays the correct total balance. **Reference**: <img width="1422" height="490" alt="6482797" src="https://github.com/user-attachments/assets/95b35ac7-f410-413b-8ef9-29f97f16c35a" /> [1]: https://github.com/odoo/enterprise/blob/54bfcbee37a241ae70b9bebb9cf23d76172e18fe/l10n_fr_reports/data/fiscal_declaration/report_2033_B_simplified_profit_loss.xml#L302 opw-6482797 Forward-Port-Of: odoo/enterprise#129348
This fixes several issues in the time off request process, especially around partial days, hourly requests, timezone handling, and unusual work schedules. Employees and managers should see more accurate dates, durations, and calendar behavior when creating or editing leave requests.
Original PR description
Here is the leaves behavior: Stored field readonly (shouldn't be edited): `date_from/to` -> UTC reference Stored fields editable to request: - time type in days: `request_date_from/to` - time type in…
Here is the leaves behavior: Stored field readonly (shouldn't be edited): `date_from/to` -> UTC reference Stored fields editable to request: - time type in days: `request_date_from/to` - time type in halves: +`request_date_from/to_period`, `request_duration` (multidays/solo) - time type in hours: +`request_hour_from/to` (not in the view) Computed field, (editable for a time type in hours): `request_date_hour_from/to` -> converted to the reader tz It means no more cycle exits: `request_date_hour_from/to` edited => inverse will update requests stored fields => date_from/to will be recomputed based on the request stored fields The purpose of using `request_date_hour_from/to` is to display for the user the same range of hours for employees with different tz Other little fixes around: - _to_utc(): round the hour to the whole minute, where the carry can reach the hour, and stop at the end of the day, as float_to_time takes neither a minute 60 nor an hour 24. - _split_leaves(): both parts are whole where they are cut and carry the request_duration their periods describe, dates included, instead of the half day copied from the original. - _get_hours_for_date(): a day the schedule leaves out borrows the hours of the nearest day it names, not the widest hours of the whole schedule, which no single day of a two week rota works; a schedule naming no hour at all falls back on an average day centred on midday, where it used to leave the request without any extent. - _compute_last_several_days(): a request whose end precedes its start is one being edited, not one of several days, so moving one bound of the pair before the other catches up no longer snaps the duration back onto whole days. task-6459867
The Time Off Gantt views now better reflect the updated fixed leave request process and align dates with each user's local wall-clock time, like calendar views. This helps HR teams and managers see leave schedules more accurately in overview and management screens.
Original PR description
Gantt adapted with the new fixed leave request process Gantt view timezoned based on the wall clock of the user as calendar views now (Overview and Management) task-6459867
Users sending Colombian support documents to DIAN now see a clear message when the required operation mode has not been configured. This replaces a confusing server error with guidance on what is missing and where to fix it, helping businesses complete electronic document submissions faster.
Original PR description
**Steps to reproduce:** * Install `l10n_co_dian`. * Configure a company with the Colombian localization. * Set up a DIAN operation mode for Electronic Invoices only (no Support Documents mode). *…
**Steps to reproduce:** * Install `l10n_co_dian`. * Configure a company with the Colombian localization. * Set up a DIAN operation mode for Electronic Invoices only (no Support Documents mode). * Create a vendor bill marked as a Support Document and click **Send to DIAN**. **Observed behavior:** * A cryptic server error is raised: *"TypeError: unsupported operand type(s) for +: 'int' and 'str'"* * No actionable information is shown to the user. **Cause:** * `_add_document_config_vals` assigns `vals['l10n_co_dian_operation_mode']` via `.filtered()`, which returns an empty recordset when no matching operation mode exists. * Accessing a `Char` field on an empty recordset returns `False` (a `bool`, which is a subclass of `int` in Python). * Concatenating `False` with strings in the `sha384` hash calculation raises the `TypeError`. * The missing-mode guard only existed in the commercial events path, not in the main invoice export path. **Fix:** * Raise a descriptive `UserError` that tells the user which mode is missing and where to configure it. opw-6499321 Forward-Port-Of: odoo/enterprise#130853 Forward-Port-Of: odoo/enterprise#128935
Reconciliation model labels are now applied using the company’s language, so automated and manual reconciliation create journal items with the same wording. This prevents misleading labels when users work in different languages or models are duplicated and edited.
Original PR description
### Problem `label` on `account.reconcile.model.line` is a **translatable** field, but its value is written onto the journal item created when the model is applied (`account.move.line.name`). That…
### Problem
`label` on `account.reconcile.model.line` is a **translatable** field, but its value is
written onto the journal item created when the model is applied (`account.move.line.name`).
That means the label is read in the language of whoever applies the model:
- a user working in another language writes the translated value;
- the auto-reconciliation cron writes the **source** value, since it runs as OdooBot.
So the very same reconcile model ends up writing two different labels on the journal items,
depending on who applied it.
### How it shows up
It becomes visible when a reconcile model is created by **duplicating** an existing one and
the label is then edited while working in a non-source language. The translation holds the
new text, while the source value silently keeps the label of the original model — and the
source value is exactly the one the cron writes. The result is a set of journal items where
some carry the intended label and some carry the label of an unrelated model.
### Fix
The journal item belongs to the company, so the label is read in the **company** language
via a small `_get_aml_label()` helper, instead of the language of the current environment.
It falls back to the current behaviour when the company has no language set.
`_prepare_aml_vals()` is the only place in 18.0 that reads `self.label` for the journal item.
### Test
Adds `TestBankRecWidget.test_auto_reconcile_model_label_uses_company_lang`: a reconcile model
whose line label is translated in the company language, applied by the auto-reconciliation
cron running in the source language, and asserts the journal item carries the company-language
label.
```
odoo -d <db> -u account_accountant --test-enable --stop-after-init \
--test-tags /account_accountant:TestBankRecWidget.test_auto_reconcile_model_label_uses_company_lang
```
Without the fix the test fails with `[{'name': 'Frais bancaires'}] != [{'name': 'Bank fees'}]`;
with the fix it passes. The full `account_accountant` suite was also run on a clean 18.0
database: 203 tests, 0 failed, 0 errors.
Forward-Port-Of: odoo/enterprise#130865
Forward-Port-Of: odoo/enterprise#128433This fix restores correct height settings for website map sections, including simple maps that do not use a Google API key. It also brings back support for using map snippets in page templates with padding, helping website pages display maps as intended.
Original PR description
[Commit ace2431d] modified the way the height of Google maps snippets is computed. On simple map snippets (the one available without a Google API key), the height option didn't work properly or wasn't even available anymore. Additionally, [commit af49dbe8] added support to include the map snippet within a `t-call` on XML templates, together with a `padding` parameter. This was lost and not adapted when the other commit was merged in master. [Commit ace2431d]: https://github.com/odoo/odoo/commit/ace2431ddfdd7e99cf13e9a8458a109e92dd1a6a [commit af49dbe8]: https://github.com/odoo/odoo/commit/af49dbe8ccfbd6b31c899ea7699dff38d178ad4b task-6503185
Fixed an issue that caused an error when employee cashiers performed Cash In/Out operations in Point of Sale. The cash movement now records the employee correctly, helping stores continue cashier workflows without interruptions.
Original PR description
Steps to reproduce: -- - Enable Employee Login in PoS. - Log in as an employee cashier. - Perform a Cash In/Out move. - Error! Issue: -- An error occurs when making a cash move while logged in as an employee cashier. Cause: -- The cash move request array passed employee information in place of the partner ID, resulting in a database type error. Fix: -- Passed the employee ID as a separate parameter in the cash move payload, and updated the backend session to save the employee ID on the cash move record. Task- 6445993
Product identifiers sent to Google Analytics now match the identifiers used in Google Merchant Center feeds. This helps Google Ads connect Shopping ad clicks with purchases more reliably, reducing attribution mismatch warnings.
Original PR description
**Issue:** When google analytics (GA) and google merchant center (GMC) are setup, Google Ads diagonistic reports that item IDs cannot be matched to Merchant Center. **Why this happens:** `_get_google_analytics_data` sets `product.barcode or product.id` for `item_id`, while `product.feed._prepare_gmc_items` defaults to `product.default_code or product.id` for the feed's `id` field. Google Ads/Analytics attribution relies on GA4's `item_id` matching GMC's `id` for the same product to connect Shopping ad clicks to purchase events. **References:** https://support.google.com/merchants/answer/6324405?sjid=15224664355638221483-NC https://support.google.com/google-ads/answer/14943675?hl=en opw-6443326 Forward-Port-Of: odoo/odoo#287074 Forward-Port-Of: odoo/odoo#285010
This fix makes the website builder correctly remember changes to form field default values, so undo actions restore the page as expected. It also prevents stale values from remaining when switching date fields to date-and-time fields, improving editing reliability for website forms and translations.
Original PR description
The `value` property of the elements is not tracked by the history plugin, because `MutationObserver` does not produce mutations for that. This commit uses custom mutations when the `value` is changed, to restore the previous value on undo. Steps to reproduce: - Open website builder - Add a form - Set a "Default Value" on a text field - Press enter (to end preview) - Undo (with the button, or with focus out of the option's input) - Bug: The value shown in the page did not revert with undo Similar bug in translate mode task-6229671 Forward-Port-Of: odoo/odoo#287325 Forward-Port-Of: odoo/odoo#281232
The Indian GSTR POS report tests were updated to reflect that point-of-sale session closing entries now use a dedicated closing journal. This keeps report validation aligned with the current accounting flow and helps prevent false test failures.
Original PR description
Following the introduction of a dedicated closing journal in point_of_sale, session closing entries are posted in the POSC journal rather than sharing the Orders/Invoicing journal sequence. task-id: 6446274
The Stock Delivery module will once again install automatically when both Sales Stock and Delivery are installed. This prevents businesses from missing delivery-related stock functionality after recent dependency changes.
Original PR description
The `printer` module was added to dependencies of the `stock_delivery` module. Due to that, now if `sale_stock` and `delivery` are installed, this module is not being installed automatically. This commit makes sure this module is installed if these two modules are present. task-6469674 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
Secondary badges are now easier to read in both light and dark display modes. This improves visual clarity for users by ensuring badge text and backgrounds have enough contrast.
Original PR description
Before this PR:- ========================== Secondary badges are barely visible in light and dark modes. <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/552dd924-4ab4-4fd5-b0fe-b103697a0bb9" /> <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/a199ad73-bd94-42dd-aa46-1fc7fb2f9436" /> After this PR:- ========================== Make the badge text and background clearly visible in both modes. <img width="1232" height="672" alt="image" src="https://github.com/user-attachments/assets/cbff2756-f2e4-42fa-97c6-669409fd4efb" />
Fixed an issue that prevented manufacturing orders from being created on small screens when work orders and operation instructions were enabled. The change ensures the related work order keeps its operation details, so required quality checks are created as expected.
Original PR description
Steps to reproduce --- 1. Enable Work Orders. 2. On a product's BoM, add an operation carrying an Instructions step. 3. On a small screen, create a manufacturing order for that product, set the…
Steps to reproduce --- 1. Enable Work Orders. 2. On a product's BoM, add an operation carrying an Instructions step. 3. On a small screen, create a manufacturing order for that product, set the product and save. Expected: the MO is saved and the generated work order carries its BoM operation. Actual: saving raises `Missing required field 'Product' (product_id) for model 'Stock Move'`, and once that is bypassed the generated work order has no operation, so its `quality_point_ids` stays empty and no `quality.check` is created. Issue --- On a small screen the MO form resolves its x2many relations to their kanban sub-views, so the fields carried in the onchange and save payloads are only those the active sub-view declares; two relations lose data this way. `move_finished_ids` is an invisible relation that always holds the product's finished move, built on the draft by `_compute_move_finished_ids` through `_get_moves_finished_values` with `product_id` and `product_uom_qty` set. https://github.com/odoo/odoo/blob/c9012f5ae48e29ff49391b722ed798237c448805/addons/mrp/models/mrp_production.py#L1354-L1371 https://github.com/odoo-dev/odoo/commit/c9012f5ae48e29ff49391b722ed798237c448805 gave that field `mode="list,kanban"` while only a `<list>` sub-view is defined for it. https://github.com/odoo/odoo/blob/c9012f5ae48e29ff49391b722ed798237c448805/addons/mrp/views/mrp_production_views.xml#L405-L410 On a small screen the field resolves to kanban mode, but since no kanban sub-view exists its field spec comes out empty, so on the first save the client sends the finished move as an empty create and the `stock.move.product_id` NOT NULL constraint aborts the whole save, so no MO can be created on mobile. The field is invisible and never rendered, so it has no use for a kanban view in the first place; dropping the kanban mode keeps it on its list spec, which carries `product_id`, on every screen size, while the visible Components and By-Products lists are unaffected because they resolve a populated kanban sub-view. The `workorder_ids` kanban sub-view must likewise carry `operation_id`, or the generated work order is saved without an operation and its `quality_point_ids` stays empty, so no `quality.check` is created. https://github.com/odoo-dev/odoo/commit/e3f6cef5cf94391b5c018c5eb44ce1ddee99290b had restored the invisible `operation_id` on that kanban and https://github.com/odoo-dev/odoo/commit/6318895101435a0a9d4bdff0b8dbfbb17179378e dropped it again in a kanban rework, so it is restored. opw-6488529 X-original-commit: https://github.com/odoo-dev/odoo/commit/af70218f325147a51ca6e46f4827d697c7ed7801
Status indicators in kanban cards now keep a consistent size across Event, Maintenance, and Project views. This prevents cards from subtly changing height when their status changes and makes warning indicators clearer.
Original PR description
*: event, maintenance, project, web __Problem__ In kanban views, the status bubble has two issues: - The exclamation mark of `error` is too slim. - An icon and an `o_status` bullet don't take the same room: `font-size` alone doesn't constrain the glyph height exactly, so a kanban card grew or shrank slightly depending on which state it was in. __Fix__ Render the state as an `o_status` circle carrying a `priority_high` icon, scaled down to fit inside the bullet, and cap the icon with `max-height` so every state occupies the same height. Moved some SCSS rules in `web` so `event` to remove duplicate code in the other modules. task-6377407
Fixed an issue where code editor fields could cause invoice forms to crash when document extraction features were installed. The change keeps field detection accurate without changing how the editor looks or behaves.
Original PR description
Fix for #286871. opw-6543997 ### The problem `web.AceField` and `web.IrUIViewAceField` render their root div with the `o_field_widget` class, but the `Field` wrapper already puts that class on the…
Fix for #286871.
opw-6543997
### The problem
`web.AceField` and `web.IrUIViewAceField` render their root div with the
`o_field_widget` class, but the `Field` wrapper already puts that class on the
div it renders, along with the `name` attribute. Every ace field therefore
renders a nested `o_field_widget` with no name:
```html
<div name="my_field" class="o_field_widget o_field_code ...">
<div class="o_field_widget oe_form_field o_ace_view_editor oe_ace_open">
<div class="ace_editor">... <textarea class="ace_text-input">
```
Any code that goes up from a DOM node with `closest(".o_field_widget")` to find
which field was clicked stops on the inner div, finds no `name` and cannot
resolve the field.
`iap_extract` does exactly that, in a `focusin` listener on `window`, and
`account_invoice_extract` installs its renderer for `account_move_form` with
`force: true` — so it runs on every invoice form. With no name on the inner div
it builds `"<parent_field>.null"`, and since the name now contains a dot,
`getBoxType` takes the x2many branch:
```js
modelFieldType = this.props.record.data[parentField]?._config.fields[fieldName]?.type;
```
For a `widget="code"` field, `record.data[parentField]` is a plain string. It is
truthy, so the optional chaining does not short-circuit, but it has no
`_config` → `undefined.fields` → `TypeError: Cannot read properties of
undefined (reading 'fields')`, and the whole form breaks.
### Steps to reproduce
1. Install `account_invoice_extract`.
2. Put a `widget="code"` field on the `account.move` form view (with
`l10n_ar_edi` installed there are already two on the ARCA tab).
3. Give the field a value — with an empty value the error does not happen.
4. Enable developer mode and click inside the code editor.
Reproduced on a plain 19.0 runbot build.
### The fix
Drop `o_field_widget` from the root div of both ace templates, since the
wrapper already provides it. The only rule that relied on both classes being on
the same element was `.o_field_widget { &.o_ace_view_editor { ... } }` in
`fields.scss`; it becomes a descendant selector, so the rendering is unchanged.
`account_invoice_extract` / `iap_extract` could be made more defensive as well
(`?._config?.fields[...]`, or not building a `parent.child` name when the
closest `.o_field_widget` has no `name`), but that lives in enterprise and the
duplicated class looks like the actual root cause.Delivery carrier rate checks are now handled more reliably when the shipping selection window opens. This prevents DHL, FedEx, and Envia delivery workflows from failing during automated checks, helping keep shipping cost selection stable for users.
Original PR description
* - delivery_fedex_rest The delivery rate calculation now happens when `choose.delivery.carrier` wizard gets opened (see https://github.com/odoo/odoo/pull/269131). Due to that, some tests fail upon rate calculation. This commit makes sure that delivery rate is not being calculated when wizard is created. task-6276527
Depreciation models that are already linked to assets can no longer be deleted accidentally. This prevents assets from losing required setup information and becoming impossible to reset, cancel, or manage.
Original PR description
**Steps to reproduce:** * Install the **Accounting** (`account`). * Create a **Depreciation Model** (e.g. Linear, 5 years). * Create an asset, assign the depreciation model, and confirm it. * Go to…
**Steps to reproduce:** * Install the **Accounting** (`account`). * Create a **Depreciation Model** (e.g. Linear, 5 years). * Create an asset, assign the depreciation model, and confirm it. * Go to **Accounting → Configuration → Depreciation Models** and delete the model used by the running asset. * Try to **Reset to Draft** on **asset**. **Observed behavior:** * The depreciation model is deleted silently. * The asset's `model_id` FK becomes `NULL`, causing all related fields (`method`, `method_number`, `method_period`, `journal_id`, etc.) to become empty. * Any subsequent attempt to cancel, reset to draft, or delete the asset fails with a **missing required field** error, leaving the asset permanently unmanageable. **Cause:** * `account.depreciation.model` had no `@api.ondelete` guard — deletion was entirely unprotected, unlike `write()` which already blocks edits on models used by running assets. * `model_id` on `account.asset` had no `ondelete` constraint, so the database silently NULLed the FK on model deletion. **Fix:** * Add an `ondelete='restrict',` on a asset's `model_id` field to prevent deletion of a depreciation model that is in use by any asset. opw-6233210 Forward-Port-Of: odoo/enterprise#130859 Forward-Port-Of: odoo/enterprise#126979
French point-of-sale sales that encounter missing e-invoicing data will now download a standard invoice instead of an incorrect pro-forma invoice. This keeps the sale flow consistent while avoiding confusion for customers and staff; failed electronic transmission is not sent externally until the data issue is resolved.
Original PR description
## Steps to reproduce: - Create a customer with France E-Invoicing (UBL2.1) as eInvoice format in a French company - Go to the PoS, select that partner - Make a sale and ask for an invoice - The…
## Steps to reproduce: - Create a customer with France E-Invoicing (UBL2.1) as eInvoice format in a French company - Go to the PoS, select that partner - Make a sale and ask for an invoice - The downloaded invoice will be a pro-forma invoice ## Why the fix: The pro-forma should not be used here, it is because it is used as a fallback when we get an error while trying to print the invoice. https://github.com/odoo/odoo/blob/4a508586970e44367bbdbbb3cbe88ffb5a1eadb7/addons/account/models/account_move.py#L6187-L6204 As we get an error while trying to send the data with this setup, it goes to the fallback and prints a pro-forma invoice, even though this should not be the case, a regular invoice would do. This happens because when an error is found, we do not populate invoice_pdf_report_id, so it goes to the fallback. We now check if there are any errors in the order, and if there are and the customer requests an ubl_21_fr invoice, we just print the invoice as it is, without going to the pro-forma fallback, as this is not the intended flow. With this fix, we now have the same flow as we do in the sales module, that allows the sale even if the customer has missing data. It will just print the invoice and allow the sale but won't send anything to external entities. opw-6428369 Forward-Port-Of: odoo/odoo#286644 Forward-Port-Of: odoo/odoo#281420
Cancelled retail orders and order lines are now saved and marked correctly when sent to Fiskaly. This helps German point-of-sale certifications reflect cancellations accurately, reducing compliance and reporting issues.
Original PR description
In this commit: --------------- - We now store cancelled retail orders on the server and send the `storno` flag as `true` for cancelled lines and orders to ensure proper handling in Fiskaly. task: 6326042 Relataed PR: https://github.com/odoo/odoo/pull/277648 Forward-Port-Of: odoo/enterprise#130751 Forward-Port-Of: odoo/enterprise#120410
This fixes an issue where a measure defined by a report could disappear from the Measures menu after users deselected it and refreshed or filtered the pivot view. Business users can now reliably adjust filters and still find the original reporting options when they need them again.
Original PR description
TL;DR - we lose the measures from arch after a reload, if removed from activeMeasures Step to reproduce: - install pos, create few orders - go to reporting> orders> switch to pivot view - click the…
TL;DR - we lose the measures from arch after a reload, if removed from activeMeasures Step to reproduce: - install pos, create few orders - go to reporting> orders> switch to pivot view - click the `Measures` dropdown, `Order` is already selected - untick it, then apply some filter so that view reloads (ex order date) - reopen `Measures` dropdown, notice `Order` is missing form measures Cause: - view `view_report_pos_order_pivot` has `<field name="order_id" type="measure"/>` in its pivot view https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/point_of_sale/views/pos_order_report_view.xml#L10 - `order_id` is M2O field - Measure is compute from present `activeMeasure` and fields of type `["integer", "float", "monetary"]` https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/utils.js#L89-L120 - when the view is first loaded, `activeMeasure` all the fields with `type="measure"` which is directly passed to pivot's model as a metadata https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/pivot/pivot_arch_parser.js#L59-L60 https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/pivot/pivot_view.js#L41 - when we toggled the `order_id` from measure and reloaded, `order_id` is popped from `activeMeasure` and as it's field type is `many2one` it is not considered for `measures` in `computeReportMeasures` Fix: - maintain the measures from arch separately and feed it to `computeReportMeasures` opw-6416196 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286013 Forward-Port-Of: odoo/odoo#278850
Fixed an issue that prevented invoices for Saudi Arabian customers from being printed when a tax identification number was present. This ensures Saudi e-invoicing users can print confirmed invoices without encountering an error.
Original PR description
Printing an invoice for a Saudi partner raises an error. Steps to reproduce the error: - Install ``l10n_sa_edi`` module with demo data - Switch to My Saudi Arabia Company - Create a new Partner A >…
Printing an invoice for a Saudi partner raises an error. Steps to reproduce the error: - Install ``l10n_sa_edi`` module with demo data - Switch to My Saudi Arabia Company - Create a new Partner A > Country: Saudi Arabia > VAT Number: 311111111111113 > Click on + Button > Click Tax Identification Number > Save - Create a new invoice > Customer: Partner A > Add a product > Confirm > Print the invoice Traceback: ```py AttributeError: 'account.edi.xml.ubl_21.zatca' object has no attribute '_l10n_sa_get_tin_from_vat' ``` https://github.com/odoo/odoo/blob/2e2054d4203f6453fb35ec6037cda0e2e9033cc3/addons/l10n_sa_edi/models/zatca_ubl_mixin.py#L154-L156 In [Commit], ``_l10n_sa_get_tin_from_vat()`` method is called on self to retrieve ``identification_number``. however, self is an ``account.edi.xml.ubl_21.zatca`` record, while ``_l10n_sa_get_tin_from_vat()`` is a method of ``res.partner``. So, It will lead to the above traceback when printing the invoice. Solution: Call the ``_l10n_sa_get_tin_from_vat()`` method on the partner record instead of self. [Commit]: https://github.com/odoo/odoo/commit/227f61e2cb8582d0c3269bb0ae7256250563847a sentry-7717905761 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287173
This update makes Odoo's PDF handling work consistently with the PDF library version shipped on Ubuntu Jammy, the main supported platform for Odoo 17. It also keeps compatibility with newer library versions, reducing the risk of PDF-related errors across deployments.
Original PR description
Align pypdf usage with the PyPDF2 1.26 API used on Ubuntu Jammy, Odoo 17.0's main supported Ubuntu version, and add the missing compatibility mapping for newer pypdf versions. Forward-Port-Of: odoo/enterprise#130971
This fix makes the Sign module's automated tests work consistently with different supported PDF library versions. It helps prevent false test failures during upgrades or deployments, improving release reliability without changing user-facing signing features.
Original PR description
Prior to this commit, `PageObject` was not re-exported by `odoo.tools.pdf`, forcing tests (such as `test_origin_offset_translation` in `sign`) to patch internal module paths like `PyPDF2._page.PageObject`. This resulted in test failures depending on the installed PDF library version: - `pypdf` (>= 3.0.0): `PyPDF2` submodules no longer exist. - `PyPDF2` 1.x: `PageObject` resides in `PyPDF2.pdf` rather than `PyPDF2._page`. To resolve this: - `PageObject` has been re-exported through `odoo.tools.pdf`. - Update `test_origin_offset_translation` to import `PageObject` via `odoo.tools.pdf` and use `patch.object` with standard attribute names (`cropbox`, `add_transformation`). runbot-946795 Forward-Port-Of: odoo/enterprise#130878 Forward-Port-Of: odoo/enterprise#130017
This fixes the layout of quick create forms in kanban views so field labels appear above their fields again on desktop screens. The change improves readability and restores the expected form appearance when users quickly add new records, such as tasks in Project.
Original PR description
Since odoo/odoo@9fa0bae3d8de3e129836e73623f7112a41ac1a98, the single column layout of form views is driven only by a `media-breakpoint-down(md)` rule. The kanban quick create is a narrow container…
Since odoo/odoo@9fa0bae3d8de3e129836e73623f7112a41ac1a98, the single column layout of form views is driven only by a `media-breakpoint-down(md)` rule. The kanban quick create is a narrow container whatever the viewport, so from `md` up it fell back to the desktop two columns layout and rendered each label on the left of its field instead of above it. Scope the broken table layout to `o_kanban_quick_create_form` itself instead of to the viewport, so the quick create gets the whole `form-break-table` mixin (single column, cell max-width, field widths, input dropdown width) and not only the column count. This mirrors the `:not(.o_kanban_quick_create_form)` exclusion already used a few rules above. The quick create instantiates the form renderer directly, so `o_form_editable` lands on the same element as `o_form_view`, hence the `&.o_form_editable` compound selector. Steps to reproduce: * Go to "Project" * Select any project * Click on "New" => Bug the label is not above the field task-6501365 Code made by Claude Supervised by Romeo Fragomeli (rfr) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now download files opened in the file viewer from Discuss channels without seeing an error. This restores the expected download behavior by using the request type accepted by those file links, while preserving correct downloaded filenames.
Original PR description
Description of the issue/feature this PR addresses: Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel. I've…
Description of the issue/feature this PR addresses:
Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel.
I've already submitted a ticket to Odoo: #6430586
Steps to reproduce (on a 18.0 runbot):
1. open Discuss and send an image in a channel
2. click the image to open the file viewer
3. click the download button (either the one in the header or the one in the bottom
toolbar)
The server rejects the request:
```
POST /discuss/channel/1/image/519861?filename=image.png&unique=32647b0f&download=true 405
```
and the user gets a `RPC_ERROR: Arbitrary Uncaught Python Exception` dialog reporting `405 Method Not Allowed`.
Cause: `download()` always issues a POST request, while the routes serving the attachments of a discuss channel only allow GET:
* `/discuss/channel/<int:channel_id>/attachment/<int:attachment_id>`
* `/discuss/channel/<int:channel_id>/image/<int:attachment_id>`
so the request never reaches the controller. Downloading the very same attachment from the attachment card in the conversation still works, because that one is a plain anchor navigation (GET).
This is a regression from fb152985f4b8 ("[FIX] web: download FileViewer files via blob helper"), which routed the file viewer download through `download()` in order to honor the filename sent by the server in the `Content-Disposition` header.
Only 18.0 is affected: saas-18.1 and saas-18.2 do not have the commit that introduced the regression, and from saas-18.3 on, the `urlRoute` override was dropped and channel attachments are served through the standard `/web/content` and /web/image` routes, which are not restricted to GET.
The download is still sent with POST on those branches though, hence forward-porting this up to master.
Current behavior before PR:
Downloading a Discuss channel attachment from the file viewer raises a 405 error and the file is not downloaded. Images and other file types are equally affected.
Desired behavior after PR is merged:
The file is downloaded, keeping the filename advertised by the server. The download is performed with a GET request through `downloadFile()`, which still goes through the blob helper, so the fix of fb152985f4b8 is preserved. This is already the way a file is downloaded from its url in `readonly_file.js`.
Added a test that downloads an image attachment of a channel from the file viewer and asserts the request is a GET on the channel attachment route. It fails before this fix with `POST /discuss/channel/1/image/1`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287172
Forward-Port-Of: odoo/odoo#279232Corrected formatting in the Mail and Taiwan EDI ECPay app descriptions so they display properly on the Apps page. This prevents rendering errors and avoids showing raw technical text to users.
Original PR description
Two module manifests hold a `description` whose reStructuredText does not parse. Both are rendered by `ir.module.module._get_desc` (these modules have no `static/description/index.html`, so the RST…
Two module manifests hold a `description` whose reStructuredText does not parse. Both are rendered by `ir.module.module._get_desc` (these modules have no `static/description/index.html`, so the RST path is the one used on the Apps page). ### `mail` The line introducing the list of email-enabled documents is followed by a row of dashes. In reStructuredText an underline directly below a line of text makes it a section title, so docutils treats a 102-character sentence as a heading, then fails on the indented list that follows without a blank line: ``` <string>:38: (ERROR/3) Unexpected indentation. <string>:43: (WARNING/2) Block quote ends without a blank line; unexpected unindent. ``` These are logged every time the description is rendered, and the bullet list ends up rendered as a block quote instead of a list. The dashes are dropped, since the line is a regular sentence and not a section title, and the list is surrounded by blank lines. ### `l10n_tw_edi_ecpay` The whole description is indented, which makes reStructuredText read it as a block quote. A section title is not allowed inside a block quote: ``` <string>:3: (SEVERE/4) Unexpected section title. ``` At SEVERE level this reaches the default `halt_level`, so rendering raises instead of returning a document and `_get_desc` falls back to showing the raw description in a `<pre>` block. The indentation is removed. --- Checked by rendering the `description` of every manifest under `addons/` and `odoo/addons/` with the same docutils settings `_get_desc` uses: these were the only two that reported anything, and both are clean after the change. Forward-Port-Of: odoo/odoo#285323 Forward-Port-Of: odoo/odoo#284360
Preparation receipts in Point of Sale now display whole-number item quantities without unnecessary decimal places when printed through self-ordering devices. This makes kitchen and preparation tickets clearer and reduces potential confusion for staff.
Original PR description
Fix issue where integer qty were displayed as float in preparation receipt when printed through obox (self order). task-id: 6545678 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287201
This fix ensures the editor's color picker can correctly identify the solid color tab regardless of the user's language. It prevents translated labels from causing incorrect behavior, making color selection more reliable for multilingual users.
Original PR description
### Purpose of this PR: - The color picker tabs are registered with a translated name (`_t(Solid)`), and the tab button renders that name as its only content. ColorUIPlugin read the active button's `innerHTML` and compared it to the literal string Solid to know whether the solid tab was the one in use. - Rely on the `solid-tab` class instead, which is built from the untranslated tab id. task-6441654 Forward-Port-Of: odoo/odoo#279941
This update corrects how Romanian electronic invoice attachments are read, preventing errors caused by treating stored file data as text. It helps ensure Romanian EDI invoice processing continues reliably and includes test updates to confirm the behavior.
Original PR description
A previous commit (https://github.com/odoo/odoo/commit/41fe2ebdb9cc37341362d7af829c087a5f72f9f1) added an `encode` call to a line fetching the raw attachment. This assumes the attachment value is a `str`. However, the raw attachment values are actually `bytes` objects. This PR removes the `encode` call and adjusts the tests to reflect the change. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286480
Address details from MapBox location lookups are now matched by their actual labels instead of relying on a fixed order. This prevents incorrect or failed address creation when MapBox returns missing or reordered fields, improving reliability for users who depend on map-based address entry.
Original PR description
The reverse-geocoding call to MapBox asked for five types of information (street, city, postcode, region, country) and read them back from the response by fixed position in the array. MapBox doesn't always return every requested type, or in the same order; if one is missing, every field after it shifts by one position, so the address ended up built from the wrong data, or the code crashed reading a feature that wasn't there. Each field is now looked up by its own type tag instead of its position in the array, so it's matched correctly regardless of order, and a genuinely missing type just resolves to nothing instead of corrupting the rest of the address. task-6542378 Forward-Port-Of: odoo/enterprise#130662
Website building blocks now display more reliably when dark color palettes are selected. This improves readability for previews and placed content such as countdowns, event cards, social icons, and card overlays, while also making snippet previews faster to load.
Original PR description
Fix some snippets in dark palettes task-6485048 Forward-Port-Of: odoo/odoo#284455
This update fixes a spelling error in the Helpdesk Auto Assignment group name. It improves clarity for users and administrators without changing functionality.
Original PR description
This commit fixes the typo in the "Auto Assignment" group. task-6542450 Forward-Port-Of: odoo/enterprise#130880 Forward-Port-Of: odoo/enterprise#130841
Helpdesk users can now create tickets for teams with automatic assignment without being stopped by a Time Off access error. The system still checks who is unavailable before assigning tickets, but it performs that check with the proper internal permissions.
Original PR description
Before this commit, a helpdesk user creating a ticket on a team that assigns tickets automatically got "You are not allowed to access 'Time Off' (hr.leave) records". This happens because picking the next assignee reads hr.leave as the acting user, to skip the members who are off, and a plain helpdesk user has no access to Time Off. This commit reads the employees of the members and their leaves in sudo, as whom to assign is a system decision. https://runbot.odoo.com/odoo/error/947053 Forward-Port-Of: odoo/enterprise#130796
Belgian payroll can now calculate reimbursements for employees who combine a company car with public transport or bicycle commuting. This fixes an issue where selecting a company car erased other transport choices, leading to incomplete payslip reimbursements.
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#130487 Forward-Port-Of: odoo/enterprise#129972
This fixes an issue where quickly typing and pressing Enter while creating a subtask could cause the page to show an error. The change makes the input handling more resilient when the field disappears during a save, improving reliability for users working quickly.
Original PR description
Fast Enter+type could unmount the input mid-await, leaving getEl() null while onChange still read .value directly, throwing a TypeError. Add the same null-check pattern already used in commitChanges. Steps to reproduce: 1. Go to a project and open a task in form view. 2. Create a subtask, type quickly, and press Enter immediately. 3. Repeat until the error occurs. Task-6428344 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The point-of-sale self-order experience now includes a missing compatibility fix needed during carousel transitions. This prevents an error that could occur when a carousel is closed mid-transition, improving reliability for customers using self-ordering.
Original PR description
Due to the `executeAfterTransition` fix not being included in the self order assets, a traceback would occur when the carousel component was disposed during a transition. This commit fixes the issue by including the fix file in the manifest, however some guards needed to be added due to self order not including some of the bootstrap assets. runbot-946931 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Dialog windows no longer show view switching or embedded action controls that cannot work correctly in that context. This prevents users from clicking options that appear available but do nothing or affect the background screen instead of the dialog.
Original PR description
Two elements of the control panel navigate in the current action, which isn't the action of the dialog when the action is displayed in one (target="new"), so they can't work there: - The view…
Two elements of the control panel navigate in the current action, which isn't the action of the dialog when the action is displayed in one (target="new"), so they can't work there: - The view switcher: switchView ignores all calls as soon as a dialog is open. This was done in commit [1] to fix a crash, but the switcher itself kept being displayed, so an action in target="new" with several multi record views (e.g. voip.cloud_storage_error_apps_action) displayed a view switcher that did nothing. - The embedded actions panel (added in [2]): selecting an embedded action calls doActionButton with stackPosition="replaceCurrentAction", which would replace the action in background while the dialog stays open. No action in the standard code is in that situation, so this one was only latent. The view switcher entries and the embedded actions are now both left empty for an action in target="new", which removes the switcher buttons, their small screen dropdown, the corresponding commands of the command palette and the embedded actions panel at once. [1]: https://github.com/odoo/odoo/commit/a40cbf9f040338cae31eb048002e33d10ee610f0 [2]: https://github.com/odoo/odoo/commit/f983703dfa3c5102fa818523ae419a70cc4b5230
Website text animations now keep headings and paragraphs in their original layout when a selected range spans multiple text blocks. This prevents centered or structured content from shifting unexpectedly when editors apply animations in the website builder.
Original PR description
Problem: Text animation used a single span around the full selection range. When a selection crossed block elements, this placed headings and paragraphs inside a span, producing invalid HTML and changing their layout. Steps to reproduce: 1. Drag & drop a snippet (like the "Cover" block) that contains page centered text 2. Select a range of text spanning multiple block elements within the added snippet 3. Add an animation to the selected text. Solution: This PR splits the selection by block and creates one inline animation wrapper per block instead. The builder applies animation options to the resulting elements as one group, without changing the document's block structure. task-5155887
A missing view update was added so the partner autocomplete screen correctly matches a recent script change. This prevents the feature from referencing outdated interface elements and helps keep partner lookup working as expected.
Original PR description
This commit : 66889d7c42d0247d6d7b72e742c5687c65009587 changed the JS import but not the XML tag in the view. no-task
This fixes an issue where choosing an Unsplash image for records such as product images could fail during saving. The update ensures Unsplash images are properly converted and attached before the save completes, reducing errors for users editing images.
Original PR description
**Description of the issue/feature this PR addresses:** When selecting Unsplash images from a relational field (which uses `CustomMediaDialog`), the images would fail to process or link correctly to…
**Description of the issue/feature this PR addresses:** When selecting Unsplash images from a relational field (which uses `CustomMediaDialog`), the images would fail to process or link correctly to the target record. In the web editor, Unsplash image selections are handled by patching the base `MediaDialog`. When a user selects an Unsplash image, that patch intercepts the save action and uses the `unsplash` service to notify the backend. The server then fetches the external Unsplash URL and converts it into a native `ir.attachment` record before the frontend completes the save. Because `CustomMediaDialog` is a distinct component used for relational fields, it bypassed the existing `MediaDialog` patch entirely and lacked this specialized fetch-and-convert logic. This commit introduces a parallel patch specifically for `CustomMediaDialog`. It intercepts `imageSave`, routes any Unsplash records through the `unsplash` service, and replaces the raw Unsplash records with the newly generated Odoo attachments before executing the underlying save. **Steps to reproduce:** - POS > Products > Products > choose any product > click the ‘edit’ button in the image > search something, e.g. ‘burger’ > add Unsplash Access Key and Application ID when prompted > select one of the resulting Unsplash images **Current behavior before PR:** - Error when saving an unsplash image when editing product images **Desired behavior after PR is merged:** - No error when saving an unsplash image when editing product images opw-6445843 Forward-Port-Of: odoo/odoo#285954 Forward-Port-Of: odoo/odoo#283694
Point of Sale preparation tickets now use the shop's configured timezone when printing pickup or preparation times. This prevents customer receipts from showing misleading UTC times when orders are handled by automated or public system users.
Original PR description
Preparation tickets are rendered server-side for self orders. format_datetime and format_time only fall back on env.user.tz, and the render runs under whichever user triggered it: the public user for an online payment confirmed on /payment/status/poll, OdooBot for the payment cron, the self ordering default user for an OBOX print. None of them is guaranteed to have a timezone, so the ticket could be printed in UTC: an 18:15 pickup showed as 16:15 Take the timezone from res.company.tz instead. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286794 Forward-Port-Of: odoo/odoo#285370
Spreadsheet global filter labels are now easier to see. This helps users quickly identify active filters and reduces confusion when working with spreadsheets.
Original PR description
Before this commit: The global filter's pill was not visible enough for the user. Added back the "bg-primary" class that was applied in anterior versions. Task: 6535214
The accounting logo is now displayed correctly in tax return activities. This makes these activities easier to recognize and keeps the accounting experience visually consistent for users.
Original PR description
Before PR: - Accounting logo was not visible in Tax return activities. After PR: - Accounting logo is visible in Tax return activities. task-6463584 Forward-Port-Of: odoo/enterprise#130721 Forward-Port-Of: odoo/enterprise#129501
This fix prevents Point of Sale from trying to reload register data after a session has already been closed. It avoids an error that could interrupt synchronization and helps keep end-of-day register closing more reliable.
Original PR description
When the client dispatches a synchronisation right after closing the register, `_notify_synchronisation` still calls `load_data` on `current_session_id`, which is then empty. The empty session leads to an empty `pos.config`, and `product.template._load_pos_metadata` raises an IndexError while accessing `data['pos.config']['records'][0]`. Skip the loading in that case and only send the notification, as there is nothing to load without an open session. Runbot Error-[946591](https://runbot.odoo.com/odoo/error/946591) Task-[6522054](https://www.odoo.com/odoo/project/1737/tasks/6522054)
The messaging menu now presents empty tab content with better spacing and more balanced text, making it easier to read. It also clears the search field when users switch tabs, avoiding confusing filtered results from a previous tab.
Original PR description
See details in each commit. Summary: - less bloated in "channels" empty tab, with more spacing - more balanced text of all empty tabs - clear search term on tab change <img width="727" height="1142" alt="Screenshot 2026-09-09 at 00 30 13" src="https://github.com/user-attachments/assets/46acff39-ee92-4cf6-8504-c915dcc3db27" />
This fix prevents users from saving public holidays without the payroll information needed to calculate payslips. It avoids payroll creation failures when a holiday falls in the payslip period and keeps holiday records consistent across views.
Original PR description
**Steps to reproduce:** 1. Install Payroll and Time Off modules on v19.2. 2. Create a public holiday via the form view (Time Off -> Configuration -> Public Holidays). Do not enter a work entry type…
**Steps to reproduce:**
1. Install Payroll and Time Off modules on v19.2.
2. Create a public holiday via the form view (Time Off -> Configuration -> Public Holidays). Do not enter a work entry type and save.
3. Open Payroll and try to create a payslip for any employee in the same month as the public holiday you will face below traceback.
**Issue:**
The `work_entry_type_id` is required for payroll calculations. If it is null the `_round_days` calculation evaluates an empty recordset, producing a [ValueError](https://github.com/odoo/enterprise/blob/39095789c2b6a7e558d11f479a249871b3b800b6/hr_payroll/models/hr_payslip.py#L1021
).
While in this [PR](https://github.com/odoo/odoo/pull/254666/changes) made this field was made required in the
list view, it was missed in the form view. This allows users to save a holiday without a work entry type, crashing payslip generation later.
**Solution:**
Make the `work_entry_type_id` field required in the form view as well to prevent the creation of inconsistent public holiday records.
**Traceback:**
```.py
File "/home/odoo/src/enterprise/saas-19.2/hr_payroll/models/hr_payslip.py",
line 1021, in _round_days
day_rounded = float_round(days, precision_rounding=precision_rounding,
rounding_method=work_entry_type.round_days_type)
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/float_utils.py", line 152, in
float_round
raise ValueError(msg)
ValueError: unknown rounding method: False
```
opw-6477587
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285597
Forward-Port-Of: odoo/odoo#283762Inventory users without Accounting permissions can now view and create Indian E-Waybills without access errors. This removes a permission blocker in warehouse workflows and helps shipments proceed more smoothly.
Original PR description
Before this commit Inventory users without Accounting permissions could get an Access Error when viewing or creating an E-Waybill because they could not access the required document types. After this commit Inventory users can now view and create E-Waybills without an Access Error. task-6515093 Forward-Port-Of: odoo/odoo#287121 Forward-Port-Of: odoo/odoo#285023
This fixes an issue that could block users from changing the prefix or suffix on date-based sequences. The change prevents an error during editing so sequence configuration updates can be saved normally.
Original PR description
Currently an exception is generated when the user tries to change the value of `Prefix` or `Suffix` in sequence as the following steps - Create a sequence with `Use subsequences per date_range` and…
Currently an exception is generated when the user tries to change the value of `Prefix` or `Suffix` in sequence as the following steps - Create a sequence with `Use subsequences per date_range` and add any `From` and `To` dates - Save record > Change the value of `Prefix` or `Suffix` Error: `TypeError: %d format: a real number is required, not NewId` This issue was introduced by the recently refactored changes in commit [1], which added an onchange method for the prefix and suffix fields. When the user changes either field, the onchange is triggered and recomputes all dependent fields, including `_get_number_next_actual` on `ir.sequence.date_range`. During this computation, the record contains the `NewId` record. As a result, using `%03d` to format the record ID raises the reported error, since NewId cannot be formatted as an integer. This commit fixes the issue by defaulting `number_next_actual` to `0` when `_get_number_next_actual` is invoked with a `NewId` for the related sequence while computing the value during `onchange`. [1]: https://github.com/odoo/odoo/commit/387b2289da68454599666bf96844b22c41c5cc55 Sentry-7609468821 Forward-Port-Of: odoo/odoo#277766
The live map now shows technicians one by one as their locations are found, instead of waiting for every address lookup to finish. This reduces delays when using OpenStreetMap and helps dispatchers see field activity sooner.
Original PR description
Opening the live map took a long time whenever technicians were sharing their live location and OpenStreetMap was used to find their address, since only one address lookup can be done per second, and every technician had to be fully processed before anything was shown on the map. Technicians are now displayed on the map as soon as their address is found, one by one, instead of waiting for all of them at once, similar to the way customer pins are already handled. task-6524180 Forward-Port-Of: odoo/enterprise#130648
The Discuss app header now correctly sizes itself when a private chat shows both a short contact name and local time information. This prevents text from being cut off or overflowing, making chat headers clearer for users in different time zones.
Original PR description
Before this commit, when making a private chat conversation with someone with a short name and with different timezone, the header of the Discuss app was narrower than its text content. This happens because the computation of header size was not taking into account the subtitle part, which this commit fixes. Before / After <img width="172" height="60" alt="Screenshot 2026-09-07 at 21 47 21" src="https://github.com/user-attachments/assets/2644d712-4a50-4e0e-bd08-538ecc366eb9" /> <img width="189" height="62" alt="Screenshot 2026-09-07 at 21 47 07" src="https://github.com/user-attachments/assets/f0ef502c-431b-4a12-8c9a-5407460e5690" />
The AI cleanup process now correctly finds content using older embedding models when those models are retired. This helps ensure stored AI data can be kept compatible with supported models instead of being missed by scheduled maintenance.
Original PR description
The embedding model deprecation cron starts by searching for chunks that are embedded using a model that hasn't been deprecated. However, due to an optimization in the ORM (optimize_type_selection),…
The embedding model deprecation cron starts by searching for chunks that are embedded using a model that hasn't been deprecated. However, due to an optimization in the ORM (optimize_type_selection), the search doesn't return any result. A domain that uses the 'not in' operator is converted by the optimization to use the 'in' operator and the values are replaced by the difference between the available selection values (self._selection) and the values in the domain. So, given that the selection values of the embedding_model field are the non deprecated embedding models and the search domain of the cron is ['embedding_model', 'not in', non deprecated embedding models] , the final domain will be ['embedding_model', 'in', non deprecated models list - non deprecated models list] = ['embedding_model', 'in', []] which will retrieve nothing from the DB because all records have an embedding_model. The main issue is that the optimization assumes that the available selection values are static. However, an old embedding model can be deprecated and a new one added which makes the optimization fail. So, the selection values are changed to be computed dynamically which will be skipped by the optimization. Forward-Port-Of: odoo/enterprise#128130
Nilvera refund documents in Turkey are now recognized as refunds even when they arrive with positive amounts. When possible, the refund is also linked to the original invoice, improving accounting accuracy and traceability.
Original PR description
# Description of the issue/feature this PR addresses: Nilvera can send refund documents as Invoice with refund-specific InvoiceTypeCode values. # Current behavior before PR: The default UBL import logic only treats an Invoice as a refund when its amount is negative. As a result, Nilvera refund documents sent as Invoice with positive amounts are imported as invoices. Also, imported refunds are not linked to their original invoice. # Desired behavior after PR is merged: Nilvera refund documents using refund-specific InvoiceTypeCode values are imported as refunds. When a unique match is found, the imported refund is linked to its original invoice through reversed_entry_id. task-id-5948275 I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/odoo#286964 Forward-Port-Of: odoo/odoo#259672
This fix changes how mail update tracking data is packaged so it stays compact even when older database activity remains open for a long time. It helps prevent memory errors and improves reliability without changing what users see or do.
Original PR description
The store version snapshot encoded in progress transactions (xip) as a bitmap spanning the whole [xmin, xmax) range, so its size grows with how far apart those bounds are rather than with how many transactions are actually in progress. A single long-lived transaction can push that range into the hundreds of thousands, leading to memory errors, most of it being zeroes. Sending it as a list of strings is much smaller (95-98% smaller tested on odoo). 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#287191
SEPA direct debit XML files now include a special scheme name field only for Nordea countries where it is required. This prevents Italian banks from rejecting payment files that previously contained an unexpected extra field.
Original PR description
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause:…
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause: https://github.com/odoo/enterprise/commit/3c3c64b511d07fc1ba33c30363972f5b0f7283d6 added `<SchmeNm><Cd>CUST</Cd></SchmeNm>` unconditionally for all countries The original fix was intended for Nordea (Sweden) only, which requires this node explicitly The assumption that other countries would accept it was incorrect ### Steps to reproduce: - Install `account_sepa_direct_debit` and `l10n_it` - Switch to the IT company - In Settings, set SEPA Direct Debit Creditor Identifier to `BE30ZZZ300D000000042` - Create and confirm a Payment (Method: SEPA Direct Debit, any customer and amount) - Create and validate a Batch Payment with that payment - Open the generated PAIN008 XML Before the fix, `<SchmeNm><Cd>CUST</Cd></SchmeNm>` is present opw-6530996 Forward-Port-Of: odoo/enterprise#130304
The GST token refresh process no longer overwrites the stored token with an empty or unrelated response value. This helps prevent avoidable GST reporting authentication issues while keeping the existing token valid for longer as intended.
Original PR description
Previously, `_cron_refresh_gst_token` updated the value of `l10n_in_gstr_gst_token` when refreshing the GST token using `response.get('txn')`.
However, the response received during a token refresh is: `{'status_cd': '1', 'status_desc': 'If previous Auth Token is found'}`
The GST token itself remains unchanged during a refresh; only its validity is extended. Therefore, writing `l10n_in_gstr_gst_token` with `response.get('txn')` is unnecessary and incorrect.
This commit removes that write operation.
Forward-Port-Of: odoo/enterprise#130726
Forward-Port-Of: odoo/enterprise#130313French invoices now show the “VAT due on debits” wording only when it is relevant for service taxes with a non-zero amount. This prevents misleading or unnecessary wording on export and international invoices with 0% VAT, improving invoice accuracy for French accounting compliance.
Original PR description
**Purpose** Follow-up to fix two issues reported in #277109 regarding the "TVA exigible d'après les débits" mention on French invoices. **Fixes Applied** 1. **Tax Scope Mismatch:** Changed `t.tax_scope == 'consu'` to `t.tax_scope == 'service'`. To trigger the exigibility mention on a service product, the user will configure a proper "service" scoped tax, not a goods tax. 2. **International/Export Invoices:** Added a check for `amount != 0`. Previously, the mention would print on international export invoices if the applied 0% tax had exigibility set to `on_invoice`. This hides the redundant mention for 0% exports. Forward-Port-Of: odoo/odoo#277468
Portal users can now update their preferred electronic invoicing format even when they have added a company name to their address. This prevents the field from appearing empty later and helps ensure invoice delivery settings remain accurate.
Original PR description
Steps: - Install accounting app. - Login with portal user and set `Company name` on `my/address`. - Try to edit `Electronic Format` field on my details. Issue: - `Electronic Format` field stays empty. Cause: - Since [PR](https://github.com/odoo/odoo/pull/211043) when user set `Company name` on the portal it'll create parent company and since `Electronic Format` is computed from `commercial_partner_id`, so when I update `Electronic format` field on `my/address` it'll set that value on `invoice_edi_format_store` on current address and now when I re-open `my/address` it'll compute `invoice_edi_format` from `commercial_partner_id`'s `invoice_edi_format_store` which is 'none' and it'll set `invoice_edi_format` to False and there is no way portal user can update that company's record Fix: - Update inverse of `Electronic Format` field to properly store invoice_edi_format_store value on commercial partner. Forward-Port-Of: odoo/odoo#286599 Forward-Port-Of: odoo/odoo#277527
This update removes an unnecessary warning that appeared when generating manufacturing accounting reports with demo data. It keeps the report behavior unchanged while making automated checks cleaner and reducing noise for maintainers.
Original PR description
Runbot was showing warnings when running the test_reports test with the mrp_account and project_timesheet_forecast modules installed with demo data.
```
Unknown directives or unused attributes: {'data-oe-demo'} from <t t-out="', '.join(docs.account_id.mapped('name'))" data-oe-demo="Acme Corp."/>
```
**Root cause:**
Since data-oe-demo is an html attribute usage of it within `<t>` tag raises a warning after this [commit](
https://github.com/odoo/odoo/commit/ae4824640665fc639e03a13c341f18e73060349e) in saas-19.1.
**Solution:**
Usage of span tag instead of <t> tag ensures the same behaviour without the warning.
[runbot-939604](https://runbot.odoo.com/odoo/error/939604)
Forward-Port-Of: odoo/odoo#285666This fixes an internal test issue where a shell-based test could hang when a database environment setting was present. It helps keep Odoo's automated test suite reliable and reduces delays for developers validating changes.
Original PR description
TestCommand.test_shell spawns a subprocess running `odoo-bin shell` with stdin/stdout piped through a pty. When PGDATABASE is set in the environment, that subprocess inherits it and resolves the same db_name as the parent test process, then calls Registry(dbname) to open a shell console against it. Steps to reproduce: - export PGDATABASE=db_name - ./odoo-bin -i test_core --test-tags .test_shell Forward-Port-Of: odoo/odoo#287137
Reconciliation now creates the needed exchange difference entry when matching foreign-currency journal items on accounts that allow reconciliation. This prevents leftover balances in company currency and keeps accounting records properly balanced while preserving existing behavior for non-reconcilable accounts.
Original PR description
Steps to reproduce: 1. Create two misc entries with the same foreign currency amount but different company currency amounts, on an account with "Allow Reconciliation" enabled (one debit, one credit). 2. Go to Journal Items, select both lines and click Reconcile. Issue: No exchange difference entry is generated, so the residual amount in company currency is left unbalanced. Fix: Only skip the exchange difference when the account is not reconcilable, which keeps the deferral behaviour untouched while restoring the exchange difference entry in the standard case. Causing PR: https://github.com/odoo/enterprise/pull/108362 task-6535655 Forward-Port-Of: odoo/enterprise#130541
The Hong Kong payroll payment report now handles employees who do not have an identification or passport number recorded. This prevents the report from failing and allows payroll teams to generate payment reports reliably even when optional ID details are missing.
Original PR description
When both identification_id and passport_id are empty (False), re.sub() receives a bool and raises: TypeError: expected string or bytes-like object, got 'bool'. Fall back to an empty string and normalize the passport fallback the same way as the HKID. Task-6536846