Tuesday, August 25, 2026
19 changes · 18.0
Resolved issues and error corrections
Improves the error message shown when sending a French e-invoicing credit note in demo mode. This helps users understand what went wrong during EDI document generation and reduces confusion when resolving the issue.
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` module > Switch to `FR Company` - Activate `French e-invoicing` (Demo mode) - Create a New `Credit Note` with `FR Customer` > Send Issue: The system currently displays a confusing error message during EDI document generation. We are making the error message clearer and more user-friendly. opw-6412521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Swedish ISO20022 payment batches now generate files that correctly match the selected pain.001.001.09 format. This prevents banks from rejecting vendor payment files because their internal structure used an older format despite showing the newer version.
Original PR description
**Steps to reproduce:** - Install Accounting and l10n_se - Switch to a Swedish company (e.g. SE Company) - In Accounting settings, set "Identification" with anything - In Bank journal: * Set an…
**Steps to reproduce:** - Install Accounting and l10n_se - Switch to a Swedish company (e.g. SE Company) - In Accounting settings, set "Identification" with anything - In Bank journal: * Set an account number * Make sure "Swedish ISO20022" is available in "Outgoing Payments" * Set "pain.001.001.09" as "XML Format" in "Outgoing Payments" - Create a vendor payment: * Vendor: [a vendor with a trusted bank account] * Payment Method: Swedish ISO20022 * Amount: [any] - Confirm the payment - From the payments list, select the payment and create a batch - Validate the batch payment **Issue:** When the batch is validated, a `pain.001.001.09` file should be generated. However, its content is that of a `pain.001.001.03` file, even if the version reported in the file is `pain.001.001.09`. For example, `<ReqdExctnDt>` should contains a subnode `<Dt>` in `001.001.09`, which is not the case. It leads to the file being rejected as non-compliant to `pain.001.001.09`. opw-6472050
This fixes a Windows-specific issue that prevented Odoo's test suite from running because file paths were compared using Linux/Mac-style separators. The change helps Windows-based contributors and teams validate changes locally without hitting avoidable test failures.
Original PR description
### Description of the issue/feature this PR addresses Since February 2026, changes were made in `/tests/common.py` that were probably never tested on anything else than Linux or Mac machines. Since…
### Description of the issue/feature this PR addresses
Since February 2026, changes were made in `/tests/common.py` that were probably never tested on anything else than Linux or Mac machines. Since that time, Windows users like me (sorry) are not able to run the Odoo tests anymore on their machine. Because the problem remains to this day, I thought I'd submit a PR to fix this permanently.
I have not checked versions older than 18, but it seems the problem does not occur in Odoo 19 anymore, as the code in `/tests/common.py` has been greatly improved.
### Current behavior before PR
Running `odoo-bin` with the `--test-enable` flag never works on Windows, because the simple check on [this line](https://github.com/odoo/odoo/blob/18.0/odoo/tests/common.py#L979) fails due to Windows using backslashes instead of forward slashes in file paths.
It results in the following error (and a whole lot more afterwards as a result of that):
```
2026-08-19 10:28:44,868 48604 INFO odoo-local odoo.tests.common: C:\Apps\Python312\Lib\unittest\mock.py:1581:__enter__ setting Users._crypt_context to <function TransactionCase.setUpClass.<locals>._crypt_context at 0x000002C48DD2C540>
Stack (most recent call last):
File "C:\Program Files\JetBrains\PyCharm 2024.1.4\plugins\python-ce\helpers\pydev\pydevd.py", line 2391, in <module>
main()
File "C:\Program Files\JetBrains\PyCharm 2024.1.4\plugins\python-ce\helpers\pydev\pydevd.py", line 2372, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "C:\Program Files\JetBrains\PyCharm 2024.1.4\plugins\python-ce\helpers\pydev\pydevd.py", line 1640, in run
return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
File "C:\Program Files\JetBrains\PyCharm 2024.1.4\plugins\python-ce\helpers\pydev\pydevd.py", line 1647, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "C:\Program Files\JetBrains\PyCharm 2024.1.4\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "odoo-bin", line 8, in <module>
odoo.cli.main()
File "[REMOVED]\odoo\odoo\cli\command.py", line 76, in main
o.run(args)
File "[REMOVED]\odoo\odoo\cli\server.py", line 182, in run
main(args)
File "[REMOVED]\odoo\odoo\cli\server.py", line 175, in main
rc = odoo.service.server.start(preload=preload, stop=stop)
File "[REMOVED]\odoo\odoo\service\server.py", line 1510, in start
rc = server.run(preload, stop)
File "[REMOVED]\odoo\odoo\service\server.py", line 644, in run
rc = preload_registries(preload)
File "[REMOVED]\odoo\odoo\service\server.py", line 1414, in preload_registries
registry = Registry.new(dbname, update_module=update_module)
File "[REMOVED]\venv\Lib\site-packages\decorator.py", line 232, in fun
return caller(func, *(extras + args), **kw)
File "[REMOVED]\odoo\odoo\tools\func.py", line 97, in locked
return func(inst, *args, **kwargs)
File "[REMOVED]\odoo\odoo\modules\registry.py", line 118, in new
odoo.modules.load_modules(registry, force_demo, status, update_module)
File "[REMOVED]\odoo\odoo\modules\loading.py", line 485, in load_modules
processed_modules += load_marked_modules(env, graph,
File "[REMOVED]\odoo\odoo\modules\loading.py", line 365, in load_marked_modules
loaded, processed = load_module_graph(
File "[REMOVED]\odoo\odoo\modules\loading.py", line 284, in load_module_graph
test_results = loader.run_suite(suite, global_report=report)
File "[REMOVED]\odoo\odoo\tests\loader.py", line 118, in run_suite
suite(results)
File "C:\Apps\Python312\Lib\unittest\suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "[REMOVED]\odoo\odoo\tests\suite.py", line 43, in run
self._handleClassSetUp(test, result)
File "[REMOVED]\odoo\odoo\tests\suite.py", line 175, in _handleClassSetUp
super()._handleClassSetUp(test, result)
File "[REMOVED]\odoo\odoo\tests\suite.py", line 65, in _handleClassSetUp
currentClass.setUpClass()
File "[REMOVED]\odoo\odoo\tests\common.py", line 1076, in setUpClass
cls.startClassPatcher(cls._crypt_context_patcher)
File "[REMOVED]\odoo\odoo\tests\common.py", line 443, in startClassPatcher
mock = patcher.start()
File "C:\Apps\Python312\Lib\unittest\mock.py", line 1624, in start
result = self.__enter__()
File "C:\Apps\Python312\Lib\unittest\mock.py", line 1581, in __enter__
setattr(self.target, self.attribute, new_attr)
File "[REMOVED]\odoo\odoo\tests\common.py", line 985, in metamodel_setattr
_logger.runbot(
File "[REMOVED]\odoo\odoo\netsvc.py", line 376, in runbot
self.log(logging.RUNBOT, message, *args, **kws)
```
### Desired behavior after PR is merged:
The test suite runs without problems on Windows.
Btw, it would probably be better to use `pathlib` instead as a general improvement for all places in the code where local paths are being handled, but that's out of scope here now.
---
- [x] I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThe Brazilian AvaTax sales module now includes the needed dependency so it can be installed reliably when automatic installation is skipped. This prevents setup failures caused by missing sales tax fields, helping deployments and upgrades complete without manual workarounds.
Original PR description
When installing l10n_br_avatax_sale with --skip-auto-install, you'll get an error about the l10n_br fields listed in views/sale_order_views.xml, because these fields don't fully exist without sale_external_tax. This happens because they're defined on a mixin, which is an abstract model. Abstract models only add their fields to a model that actually lists them in `_inherit`. sale.order should list this mixin, but currently doesn't. Adding that dependency is an unstable fix, so it will be added in master (20.0, or 20.1) runbot-237866
The lunch ordering test now waits for the intended product to appear after changing location before selecting it. This prevents occasional failures caused by stale demo products being selected, making automated validation of the Lunch app more dependable.
Original PR description
The lunch order tour selects `Farm 1` before ordering a product. However, it only waits for the location input to be updated before clicking the first kanban record. With demo data installed, a product from the previous location can still be displayed while the product model is being reloaded. The tour can therefore order a demo product instead of the product created by the test. This notably fails during weekends when the corresponding demo vendor is unavailable. To fix we need to wait for the product created by the test before clicking it. Besides selecting the intended product, this also ensures that the product reload following the location change has completed. [error-181572 ](https://runbot.odoo.com/odoo/error/181572) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The change makes an internal sales timesheet profitability test ignore unrelated price list data so expected values stay consistent. This helps prevent false test failures when other installed modules introduce discounts, improving release reliability without changing customer-facing behavior.
Original PR description
The project profitability test assumes that the service product is sold at its list price. However, some modules such as `pos_pricer` add a globally applicable pricelist in their data. In 18.0, this pricelist can be selected for the test partner even when the pricelist feature is disabled, causing a discount to be applied and the expected profitability amount to differ. The fix is to remove existing pricelists in the test, as done in other tests affected by the same issue, so that the sale order price is deterministic. [error-944526](https://runbot.odoo.com/odoo/error/944526) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Copying an existing image linked to another record now reuses the appropriate attachment instead of leaving behind an unnecessary duplicate. This keeps stored files cleaner and avoids redundant attachments when users copy image content.
Original PR description
Copying an image attachment already linked to another record could leave a redundant duplicate behind instead of reusing the existing one. opw-6463012 Forward-Port-Of: odoo/odoo#282287
Users auditing accounting reports can now switch from the journal item list to other available views such as pivot, graph, and kanban. This makes it easier to analyze report details in the format that best supports the review.
Original PR description
Problem: When auditing reports, the audit cell action was only showing the journal items in the list view, and not enabling other view modes (pivot, graph, kanban). Steps to reproduce: 1. Go to Accounting > Reporting > Balance Sheet 2. Click on any cell with a number in the report 3. Notice how the journal items are only shown in the list view, and you cannot switch to other view modes. Cause: The action was hardcoded to only show the list view. opw-6403704
This update changes a small piece of internal code style so automated quality checks pass consistently. It does not change business behavior, but helps keep the platform maintainable and aligned with coding standards.
Original PR description
Ruff checks on runbot flagged `while 1:` Preferred syntax is to use `while True` [UP048](https://docs.astral.sh/ruff/rules/while-one) runbot-945983 Forward-Port-Of: odoo/odoo#283962
Argentinian accounting users can now create invoices for foreign customers even when export journals are unavailable or archived. Instead of stopping the process with an error, the system falls back to a standard invoice type so sales work can continue.
Original PR description
### Issue before this commit: Before this commit, users were completely blocked from creating an invoice for a foreign partner (e.g., "Cliente del Exterior") if all exportation journals were archived…
### Issue before this commit: Before this commit, users were completely blocked from creating an invoice for a foreign partner (e.g., "Cliente del Exterior") if all exportation journals were archived or unavailable, as the system would immediately trigger a RedirectWarning error. ### Steps to reproduce the issue: 1. Download Accounting and l10n_ar 2. Go to contacts and create a new one with: 1. Country as United States 2. VAT number ex. 55000002126 3. AFIP Responsibility Type as Cliente del Exterior 3. Go to Journals, filter for sales journals and archive: 1. Electronic Exportation Invoice (FEX) 2. Expo Sales Journal 4. Go to invoices and create a new one for the client you just created 5. As soon as you insert the client you will receive the error: You are trying to create an invoice for foreign partner but you don't have an exportation journal ### Cause of the issue: https://github.com/odoo/odoo/blob/014d58e3204d17db6dcba3c8ab7d8ad35003300e/addons/l10n_ar/models/account_move.py#L186-L189 The _onchange_partner_journal method rigidly enforced the use of an exportation journal for foreign AFIP responsibility types (codes 8, 9, and 10). If the query failed to find an active export journal, the code intentionally threw a hard error instead of providing a fallback mechanism. ### Reason to introduce the fix: This fix is introduced to prevent unnecessary workflow blocks. By catching the missing journal and defaulting the document type to "Invoice B" (code 6), the user can now successfully generate the invoice using a standard domestic sales journal without being forced to configure an exportation journal. opw-6442501 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Employees viewing their own profile will now consistently see themselves marked as present, even when the page is the first one opened. This removes a small confusing status display issue without changing broader messaging or presence behavior.
Original PR description
**Steps to reproduce** 1. Install `hr`. 2. Go to the form view of your own employee. 3. Refresh the page. Issue: the presence status indicator on top of the employee's image doesn't show the employee as online. The issue is only reproducible if it is the first page loaded and no other pages are opened. **Cause** The issue only happens on first page load, because the websocket is only opened after the view is rendered. So, if `im_status` is computed for the view, its value will be computed before `bus.presence` is updated for the current user. **Change** To avoid this small inconsistency, we can consider the current user should always see their linked employee as present. This simple solution avoids making potentially breaking changes in `bus`. opw-5070228
Point of Sale sessions can now close correctly when orders include both a tracked product and kit products that use it as a component. The fix adds up quantities across matching order lines, preventing an error that blocked session closure.
Original PR description
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The…
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The Kit product - A combination of Product A and the Kit product 4. Create three different orders with these combinations. 5. Try to close the PoS session. **Issue :** An error occurs when attempting to close the PoS session. The issue is in the pos_mrp module, specifically in the _get_lot_line_qty method. When accessing the following line: `lines_data[move.bom_line_id.bom_id.product_tmpl_id.product_variant_id.id]['order_lines'].qty` we expect order_lines to contain a single record. However, in this scenario, multiple order lines can be returned for the same product. As a result, accessing .qty directly on order_lines raises a singleton error. **Solution :** With this fix, we first retrieve the quantity from each order line and thensum the quantities together. This ensures that multiple matching order lines are handled correctly and prevents the singleton error when closing the PoS session. opw-6442765 Forward-Port-Of: odoo/odoo#281622
This fix ensures Odoo correctly refreshes whether taxes are marked as used when related accounting, sales, purchase, expense, or point-of-sale records change. This helps prevent stale tax information from appearing in business workflows and reports.
Original PR description
Currently, `is_used` is computed using queries on `account.move.line`, `account.reconcile.model.line`, etc. As a result, it has no depends and is not automatically updated when records in either model are created, modified, or deleted. This commit reverse M2M fields for respective models and use it as dependency to `_compute_is_used`. It also adds a missing dependency of `is_used` to `_compute_repartition_lines_str`. Forward-Port-Of: odoo/odoo#283406
This fixes an issue where users creating products in a multi-company setup could hit an access error or have the wrong Buy route selected. The system now only uses purchase routes that match the companies available to the current user, improving reliability for businesses operating multiple companies in Odoo.
Original PR description
## **Steps to reproduce:** 1. Install the Inventory and Purchase module and enable Multi-Step Routes. 2. Open the Buy route and set Company A as its company. 3. Create a user who has access only to…
## **Steps to reproduce:** 1. Install the Inventory and Purchase module and enable Multi-Step Routes. 2. Open the Buy route and set Company A as its company. 3. Create a user who has access only to Company B. 4. Log in as this user and navigate to Products. 5. Click New to create a product. 6. An AccessError is raised because the Buy route belongs to Company A, which is not accessible to the user. ## **Issue:** The buy route returned by `env.ref` is not necessarily applicable to the current company. Returning `buy_route.ids` directly can therefore cause issues when creating a product in a multi-company environment. When the user has access to multiple companies, the buy route belonging to another company can be selected during product creation. When the user does not have access to the company of the buy route, this can instead result in an AccessError. The previous implementation performed an ORM search on `stock.route`, which implicitly filtered the route according to the current environment. However, that query was removed as part of this pr https://github.com/odoo/odoo/pull/276554. ## **Solution:** Filter the route returned by env.ref against the companies available in the current environment before returning its ID. Use sudo() while filtering so that the route's company_id can be read even when the route belongs to a company inaccessible to the current user. The route is still explicitly checked against env.companies, so sudo() does not allow an inaccessible company's route to be returned. opw-6448497 Runbot Video : [Video](https://drive.google.com/file/d/1qQyJrPNwXuHtu6GXyC_78dtd_A24khFR/view?usp=sharing) Forward-Port-Of: odoo/odoo#283199
Cash basis tax reversal entries now stay in the same reporting period as the original entry when a payment is unreconciled. This prevents tax reports from showing the original tax in one month and the reversal in another, keeping period totals accurate.
Original PR description
When unreconciling a payment from an invoice with a cash basis tax, the tax cash basis (CABA) entry is reversed. The reversal is supposed to land in the same period as the origin entry so the tax…
When unreconciling a payment from an invoice with a cash basis tax, the tax cash basis (CABA) entry is reversed. The reversal is supposed to land in the same period as the origin entry so the tax report nets to zero for that period. Steps to reproduce: - Enable cash basis and create a cash basis tax (exigibility on payment) - Post an invoice dated in the past with that tax - Reconcile a bank statement line to the invoice - Resequence the cash basis entry so the month is dropped from the name (CABA/08/2026/0001 -> CABA/2026/0001) - Unreconcile the statement line Issue: The reversal CABA entry created on the last unreconcile is dated today instead of the origin entry's month. In the tax report the original tax amount stays in the statement's month while the reversal amount appears in the current month, so the two no longer cancel out. Analysis: While under a monthly journal sequence a past date returns the last day of that month, under a yearly sequence a past date within the current year returns the latter between the move date and today, moving the reversal out of the origin period. opw-6301553
Dragging the translation dialog no longer clears text a user has just entered. This prevents accidental data loss while editing product translations and makes the translation workflow more reliable.
Original PR description
Step to reproduce: - have atleast two language and install sale - open any product, hover over product, and click on Translation button - Enter a value for one of language - drag the dialog Observation: - we lose the data, we just entered and fallback to original data Cause: - Inputs used `t-att-value="term.value"`, bound to original data. Since this content is passed to Dialog via slot, it is rendered/patched as part of Dialog's render cycle, - Dragging updates Dialog's state, triggering a patch that re-evaluated the slotted template and reset input values (which comes from `term.value`) Fix: - bind value to `updatedTerms[term.id] ?? term.value` so edits survive patches triggered by the parent Dialog opw-6431521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Cancelled retail orders and cancelled order lines are now saved and clearly marked for Germany’s Fiskaly certification process. This helps ensure compliant reporting and reduces the risk of incorrect certification records when sales are cancelled.
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
This fix prevents attendance records from being incorrectly unlinked from work entries when early or batch-created attendances cross UTC day boundaries. It helps ensure HR attendance and payroll-related work entry data remain accurate in edge cases.
Original PR description
When an early attendance starts on the previous UTC day, the cleanup uses full UTC days as boundaries. This can include an unrelated work entry and remove its attendance link. Use the generated work entries as cleanup boundaries so only entries that can overlap the new entries are considered. opw-6412221 Forward-Port-Of: odoo/enterprise#127040
Helpdesk ticket forms on websites now appear in the visitor's or website's language instead of the language of the employee who configured the team. This keeps multilingual support pages consistent and avoids showing customers the wrong language.
Original PR description
When a helpdesk team has its website form enabled, a dedicated qweb view is generated from the `ticket_submit_form` template. The arch was read in the language of the user creating or editing the…
When a helpdesk team has its website form enabled, a dedicated qweb view is generated from the `ticket_submit_form` template. The arch was read in the language of the user creating or editing the team, so a team set up by an English user language produced an English form even when the website served another language. Steps to reproduce ================== 1. Set a language other than English as the website default language. 2. While your user language is English, create a helpdesk team with the website form enabled. 3. Open the team form on the website. => The form is rendered in English instead of the website language. Root cause ========== `_ensure_submit_form_view` read the template arch without forcing a language, so it used the current user's language and stored only that value on the generated per-team view. Fix === Read the template arch in the default language of the team's website, so the generated form matches the website language regardless of the user's own language. opw-6303903