Wednesday, September 9, 2026
28 changes · saas-19.4
Resolved issues and error corrections
Mentions in social posts are now matched more accurately and linked to the correct social profiles. This prevents malformed or duplicated mention text after publishing, improving the consistency of posts on Facebook and LinkedIn.
Original PR description
This commit fixes an issue with the mention regexes for social_facebook as they weren't properly replaced by the initial mechanism. The initial mechanism was introduced by [1]. Now, we check every possible mention and if it is indeed a known mention, then we replace it by the correct link to their profile. [1]: https://github.com/odoo/enterprise/commit/4dacc5fce72687680080f75feef875fbfb3dbd15 task-6026857 Forward-Port-Of: odoo/enterprise#130095
Mexican CFDI invoice PDFs now include local taxes in the totals and show the export type value. This ensures the PDF matches the official electronic invoice, reducing confusion and errors when local taxes apply.
Original PR description
In odoo/enterprise#98816 the MX invoice pdf was modified to be an exact representation of the generated CFDI document (MX EDI doc). Some info was not considered during the implementation: local taxes…
In odoo/enterprise#98816 the MX invoice pdf was modified to be an exact representation of the generated CFDI document (MX EDI doc). Some info was not considered during the implementation: local taxes and export type value. This causes the pdf total amounts to not match when generating the PDF when using local taxes. How to reproduce (using demo data for easy testing): - Install l10n_mx_edi with demo data and select `INNOVACION Y DESARROLLO...` demo company - Go to Accounting > Configuration > Taxes - Copy tax 16% (VAT(16%)) and under `Advanced Options` tab change SAT tax type (l10n_mx_tax_type) to Local - Go to Accounting > Customer > Invoices and use one of the draft invoices to INMOBILIARIA CVA. - Add the new tax under the existing line. - Post invoice and send to show Send wizard. Disable the email option and enable CFDI one if not set and generate CFDI. - Generated PDF will not have the local taxes on their totals and also exportacion value is not there This commit adds the local taxes at the tax totals table and export type value. task-6477478
This fix prevents Saudi e-invoices from being sent more than once to ZATCA when the user only has read-only access to journals. It ensures the successful submission record is saved correctly, avoiding duplicate filings and related compliance confusion.
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 fiscal declaration report now includes all relevant operating expense lines in its total. This helps businesses using the 2033 B report see a more accurate accounting income calculation and reduces the risk of reporting discrepancies.
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
Fixed an issue where the calendar's multi-create popover could lose some available Time Type options after creating and deleting working-time entries in variable schedules. Users can now continue adding entries without needing to refresh the page to restore the full list of choices.
Original PR description
Issue: The calendar multi-create popover retains its form values so they can be reused when adding entries to another selection. In a variable working schedule, this retained state incorrectly…
Issue: The calendar multi-create popover retains its form values so they can be reused when adding entries to another selection. In a variable working schedule, this retained state incorrectly restricted Time Type to the first allowed value after mass creating entries and deleting one occurrence. Refreshing the page restored all Time Type options because the form was then rebuilt from the complete backend value of `allowed_work_entry_type_ids`. Steps to reproduce: - Open a working schedule and switch it from Fixed to Variable. - Select multiple days and mass add working-time entries. - Select one of the created days and delete its entry. - Select that day again and open the Add popover. - Open Time Type and observe that only the first allowed type is available. - Refresh the page and observe that all allowed types are available again. Cause: `work_entry_type_id` is filtered by the computed `allowed_work_entry_type_ids` relation. The relational model keeps every relation ID in `StaticList.currentIds`, but only materializes the loaded page in `StaticList.records`. Since this invisible domain dependency has no related display fields, its loaded page is limited to one record. When the multi-create popover was submitted or closed, https://github.com/odoo-dev/odoo/blob/23266b3a3bf0856dc147e3780e5ac54469bbcc53/addons/web/static/src/views/view_components/multi_selection_buttons.js#L169-L180 serialized x2many values from `StaticList.records`. This reduced `allowed_work_entry_type_ids` to its first loaded ID in the retained `multiCreateValues`. Reopening the popover reused that incomplete relation, so the Time Type domain correctly evaluated against only one ID. Solution: Serialize x2many values from `StaticList.currentIds` so every related ID is preserved. For loaded records, merge the cached record data to retain edited or display values, for unloaded records, retain an ID-only value. This keeps the complete domain dependency across calendar multi-create popovers without changing the backend Time Type computation. opw-6398706 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes issues when pasting or inserting tables from sources that omit cells or use merged rows and columns. The editor now fills missing table cells so table menus and related editing features continue to work reliably.
Original PR description
Description of the issue this PR addresses: We don't support colspan/rowspan in the editor, so tables containing them can break other functionality that assumes a rectangular grid (equal cell count per row). This PR expand any rowspan/colspan into individual cells on insert. opw-6347233 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285125 Forward-Port-Of: odoo/odoo#281114
This fix prevents Global Location Numbers from being automatically copied between a company contact and its delivery addresses. Businesses can now maintain different GLNs for multiple delivery locations without one address overwriting another, improving accuracy for electronic invoicing and logistics.
Original PR description
**PROBLEM** EAN_GLN partner identifier is synced (because partner identifiers are synced by default). Meaning you can only have one GLN on a contact and delivery address sub-contact. However, it's common to have multiple delivery location for a contact, which should each have their Global Location Number. **STEP TO REPRODUCE** 1. Install account_edi_ubl_cii. 2. Create a contact. 3. On this contact, create a first delivery address contact with a GLN. 4. Create a 2nd delivery address contact with a different GLN. 5. Notice that: - On the contact, there is a new field appearing EAN/GLN with the 2nd GLN. - The GLN on the 1st delivery address contact has been replaced by the 2nd GLN. expected behavior: - 1st delivery address GLN should not be replaced. opw-6462252
Journal items created by bank reconciliation rules now use the company's language for their labels, instead of varying by the user or automated process applying the rule. This prevents inconsistent or incorrect labels when reconciliation models are duplicated and translated.
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#128433Payroll users can now open the Belgian eco voucher wizard from any pay run that includes eco vouchers. The wizard also shows only employees with eco voucher payslips in that specific batch, reducing confusion and helping process vouchers accurately.
Original PR description
Allow to open the eco vouchers wizard from any payrun that contains eco vouchers. Also, this commit limits the wizard to the employees that have a payslip with eco vouchers in that specific batch. Forward-Port-Of: odoo/enterprise#130450
Purchase receipts for subcontracted products now use the specific subcontractor location set on the vendor instead of the company's generic subcontracting location. This ensures inventory movements reflect the correct partner location and improves traceability for subcontracting operations.
Original PR description
**Issue** While confirming a PO for a subcontracted product, the receipt's move takes the company's generic subcontracting location as its source, instead of the location set on the subcontractor…
**Issue** While confirming a PO for a subcontracted product, the receipt's move takes the company's generic subcontracting location as its source, instead of the location set on the subcontractor partner. **Steps to reproduce** - On a subcontractor partner, set a "Subcontractor Location" different from the company's default Subcontracting location. - Create a subcontracting BOM for a product with that partner as subcontractor. - Create and confirm a PO for that product with the partner as vendor. - Confirm the receipt and check the move history -> The incoming move's source location is the generic company "Subcontracting" location instead of the location set on the partner. **Cause** While confirming the PO, it creates the associated receipt (picking): https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/purchase/models/purchase_order.py#L719 https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/purchase_stock/models/purchase_order.py#L206 which creates and confirms the associated moves: https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/purchase_stock/models/purchase_order.py#L384-L385 which retrieves the subcontracting location from either: - the picking's partner, or - the company, if it can't get it from the picking: https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/mrp_subcontracting/models/stock_move.py#L154-L156 At that point the move takes it from the company, since the move has no picking yet. It only gets linked to a picking right after: https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/mrp_subcontracting/models/stock_move.py#L158 https://github.com/odoo/odoo/blob/d38e85c54ab25b23e4c3930a48b704a6d34b4ecf/addons/stock/models/stock_move.py#L1625-L1642 opw-6499846
Fixes an error that could occur when users working in Arabic applied an inventory date in the Stock reporting view. The date is now saved in a system-compatible format, allowing stock quantities at a selected date to load correctly across languages.
Original PR description
Currently, an error occurs when applying the inventory date in the Stock reporting view. Steps to Reproduce: - Install the `stock` module with demo data. - Go to `Settings` > `Languages`, add…
Currently, an error occurs when applying the inventory date in the Stock reporting view. Steps to Reproduce: - Install the `stock` module with demo data. - Go to `Settings` > `Languages`, add `Arabic`, and switch to it. - Go to `Inventory` > `Reporting` > `Stock`. - In the `left-side panel`, enter an `Inventory at Date` and click `Apply`. `ValueError: time data '٢٠٢٦-٠٩-٠٩ ٠٥:١٨:٠٠' does not match format '%Y-%m-%d %H:%M:%S'` After the [recent commit] that added a date picker to the Stock report search panel, when user enters a date using Arabic numerals, the text is displayed from right to left [1]. This date is then added to the context [2]. When computing the quantities, the date value from the context [3] is passed to it, where it is converted to a datetime [4]. However, the conversion expects the date to use Latin numerals. Since the date is in Arabic numerals, this raises the error. This commit ensures that the date is serialized using serializeDateTime [5], which also uses the UTC timezone and the Latin numbering system (latn) as expected by the system. [recent commit]: https://github.com/odoo/odoo/commit/52bfa5b9bebbcb4f8042daa183edc39865036605 [1]- https://github.com/odoo/odoo/blob/7ef98548726f36856d78c745679b14b0165803ba/addons/stock/static/src/views/search/stock_report_search_panel.js#L39-L40 [2]: https://github.com/odoo/odoo/blob/7ef98548726f36856d78c745679b14b0165803ba/addons/stock/static/src/views/search/stock_report_search_model.js#L52-L53 [3]: https://github.com/odoo/odoo/blob/7ef98548726f36856d78c745679b14b0165803ba/addons/stock/models/product.py#L146 [4]- https://github.com/odoo/odoo/blob/7ef98548726f36856d78c745679b14b0165803ba/addons/stock/models/product.py#L162 [5]: https://github.com/odoo/odoo/blob/7ef98548726f36856d78c745679b14b0165803ba/addons/web/static/src/core/l10n/dates.js#L552-L560 sentry-7629069474 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Pivot report measure options now remain available after users change filters or reload the view. This prevents reporting choices, such as POS order measures, from disappearing and helps users keep consistent access to their report metrics.
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
Users sending Colombian Support Documents to DIAN now receive a clear message when the required operation mode is not configured. This replaces a confusing server error with guidance on what needs to be set up, reducing support time and failed document submissions.
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#128935
Fixes an issue in the website builder where undo did not properly restore default values entered in form fields or translated content. This helps editors avoid inconsistent page content when changing, undoing, or switching field types.
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#287165 Forward-Port-Of: odoo/odoo#281232
Users can now download attachments opened in the file viewer from Discuss channels without seeing an error. This restores a common download action and prevents failed downloads caused by the wrong request method.
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#279232This fix ensures manufacturing orders created on small screens keep the correct work order operation details. As a result, required instruction and quality-check steps are created as expected, preventing missing checks during production.
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. 4. Open 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. 4. Open the generated work order: its quality-check step is missing because the work order was created without an operation. Issue --- On a small screen the MO form renders `workorder_ids` with the work order kanban sub-view, so the onchange field spec only carries that kanban's fields; with `operation_id` absent from it, the generated work order is saved without an operation and its `quality_point_ids` stays empty, so no `quality.check` is created. This exact bug was already fixed by https://github.com/odoo-dev/odoo/commit/e3f6cef5cf94391b5c018c5eb44ce1ddee99290b, which restored the invisible `operation_id` on the kanban, and then reintroduced by https://github.com/odoo-dev/odoo/commit/6318895101435a0a9d4bdff0b8dbfbb17179378e, a kanban rework that dropped the field again; this simply restores it. opw-6488529 Forward-Port-Of: odoo/odoo#285958
Helpdesk users can now create tickets for teams with automatic assignment without being stopped by time off permission errors. The assignment process still checks who is unavailable, but does so as a system action so regular helpdesk work is not interrupted.
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
Odoo now blocks users from deleting a depreciation model if it is still linked to active, paused, or closed assets. This prevents asset records from losing required accounting settings and becoming impossible to manage later.
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 `@api.ondelete(at_uninstall=False)` method `_unlink_if_no_running_assets()` on `account.depreciation.model` that raises a `UserError` listing the affected asset names when a deletion is attempted while any linked asset is in `open`, `paused`, or `close` state — mirroring the protection already present in `write()`. opw-6233210 Forward-Port-Of: odoo/enterprise#130859 Forward-Port-Of: odoo/enterprise#126979
Odoo now uses the same product identifier for Google Analytics purchase events as it does for Google Merchant Center product feeds. This helps Google Ads correctly connect Shopping ad clicks with purchases, improving attribution and reducing diagnostic 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:** `order_lines_2_google_api` 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 change fixes an issue that could prevent invoices from being printed for Saudi Arabian customers with tax identification details. Businesses using Saudi electronic invoicing can now print these invoices without encountering an unexpected 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
Belgian payroll corrections now calculate the employment bonus correctly. This helps ensure adjusted payslips reflect the right amounts, reducing payroll errors and follow-up corrections.
Original PR description
In case of correction, the employment bonus was wrongly computed. This commit fixes the issues with a more generic approach. Forward-Port-Of: odoo/enterprise#130158
SEPA Direct Debit files now include a special bank identification field only for Nordea countries that require it. This prevents Italian banks from rejecting direct debit files due to an unnecessary extra field, while preserving compatibility for Nordea users.
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
Nilvera refund documents for Turkish e-invoicing are now recognized as refunds even when they arrive with positive amounts. When the original invoice can be uniquely identified, the refund is linked to it, improving accounting accuracy and reconciliation.
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 the Mail app shares information about ongoing database updates, using a compact list instead of a large mostly empty map. It helps prevent memory errors in cases with long-running background activity and makes synchronization data much smaller.
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
Cancelled retail orders are now saved on the server and marked correctly when sent to Germany's Fiskaly certification service. This helps ensure compliant reporting for cancelled sales and reduces the risk of incorrect fiscal records.
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#130175 Forward-Port-Of: odoo/enterprise#120410
Portal users can now update the electronic invoicing format on their address details even when a company name is set. This prevents the field from appearing empty again and helps keep invoicing preferences accurate for customer records.
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
Fixed an accounting issue where reconciling matching foreign currency journal items could leave an imbalance in the company currency. The system now creates the required exchange difference entry for reconcilable accounts, helping keep accounting balances accurate.
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
Peruvian electronic invoices now include cash rounding in the final amount due sent to SUNAT. This prevents mismatches between the rounded amount shown on the invoice and the payable amount reported in the XML, reducing validation or compliance issues.
Original PR description
Steps to reproduce ------------------ 1. On a peruvian company, set a cash rounding method on an invoice 2. Post the invoice and generate the SUNAT UBL 2.1 XML -> the rounding is in…
Steps to reproduce ------------------ 1. On a peruvian company, set a cash rounding method on an invoice 2. Post the invoice and generate the SUNAT UBL 2.1 XML -> the rounding is in `PayableRoundingAmount` but `PayableAmount` still has the amount before rounding! Why it's happening ------------------ The generic code computes `PayableAmount` from `amount_residual`, and Peru overrides it to be the total tax included of the XML minus the prepaid amounts, because the residual can not be used there. Then odoo/odoo@b847552872ad changed the meaning of the totals. The cash rounding line is not part of the base lines anymore, its amount is kept aside in `cash_rounding_base_amount_currency` and the totals do not contain it anymore. The generic code stays correct because `amount_residual` already has the rounding inside but the Peru total using `tax_inclusive_amount_currency` is now the amount before rounding and this is what ends up in the `PayableAmount`! The fix ------- Add the cash rounding amount when computing the `PayableAmount`. opw-6509677 Forward-Port-Of: odoo/enterprise#130732 Forward-Port-Of: odoo/enterprise#129983