Daily updates from Odoo
Friday, August 22, 2025
34 changes · saas-18.3
Resolved issues and error corrections
Refunds made through Viva payment terminals now retain their link to the original payment even if the Point of Sale page is refreshed. This prevents staff from having to present a customer card again for refunds that should be processed automatically.
Original PR description
Steps to reproduce: 1. Configure a PoS with a Viva payment terminal 2. Complete an order using the Viva payment method 3. Start to refund the order, and get to the Payment screen 4. At this point, refresh the page 5. Now continue with the refund, using the Viva payment method **Expected behaviour**: The refund is referenced to the original payment, meaning it can be automatically completed without a card. **Actual behaviour**: The refund reference is lost after refreshing, so an unreferenced refund is performed, requiring a card to be presented. The fix is to store the refund reference in the `uiState`, not just on the plain JS object. This way it is saved to the indexedDB. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Accounting reconciliation now pairs matching debit and credit lines for the same partner more consistently. This prevents confusing behind-the-scenes partial reconciliation amounts while keeping the visible reconciliation result correct.
Original PR description
**Steps to reproduce:** - Install Accounting - Go to "Accounting / Accounting / Journals / Journal Entries" - Create the following MISC entries in this order: 1) | Account | Partner | Debit | Credit…
**Steps to reproduce:** - Install Accounting - Go to "Accounting / Accounting / Journals / Journal Entries" - Create the following MISC entries in this order: 1) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner A | 1000 | 0 | | Account X | Partner A | 0 | 1000 | 2) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner B | 1001 | 0 | | Account X | Partner B | 0 | 1001 | 3) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner C | 1002 | 0 | | Account X | Partner C | 0 | 1002 | 4) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner C | 0 | 1002 | | Account X | Partner C | 1002 | 0 | 5) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner B | 0 | 1001 | | Account X | Partner B | 1001 | 0 | 6) | Account | Partner | Debit | Credit | | ------------------ | --------- | ----- | ------ | | Receivable Account | Partner A | 0 | 1000 | | Account X | Partner A | 1000 | 0 | - Go to "Accounting / Accounting / Journals / Journal Items" - Select the 6 created lines linked to the Receivable Account - Reconcile them **Issue:** The 6 lines are fully reconciled, but when checking the amounts of the partial reconcile records (not visible in the UI), the debit and credit amounts are matched by their actual order. So, the first debit line of 1000 is matched with the first credit line of 1002, which results in a residual credit of 2 that is then matched with the second debit line of 1001, which leads to a residual debit of 999 and so on. This generates weird amounts in the partial reconcile records. **Solution:** In the case there are several lines with different partners, the lines can be sorted by partner to try to match the lines with the same partner together. opw-449356 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223815 Forward-Port-Of: odoo/odoo#223512
This fix makes automated checks for public discussion channels more reliable by preventing repeated test runs from confusing messages with each other. It reduces false failures in validation pipelines, helping teams ship mail-related updates with greater confidence.
Original PR description
This tour had many race conditions in the past and keeps having them. Some of them are actually due to the fact the tour is ran twice, but the selectors completely ignore this fact, leading to unexpected results. The message body is now updated before the second run to avoid confusion and the selectors are adapted to always target the message of the current run. Also remove the reload for emojis as they are showing immediately after being added. Also remove the useless comments that makes the test twice as long to read and to understand. https://runbot.odoo.com/odoo/runbot.build.error/230901 Forward-Port-Of: odoo/odoo#223839 Forward-Port-Of: odoo/odoo#223807
This fixes incorrect unit prices on invoices created from sales orders that include down payments and global discounts. Invoice line prices now better match their subtotals, reducing confusion and improving billing accuracy.
Original PR description
Steps to reproduce 1. Create a sale order with a product line for 14,990.00 and a 0% tax. Make sure the product's product category has a Downpayment Account set on it. 2. Create a global discount for 990.00. 3. Create an invoice. Notice how the invoice lines' price_unit are respectively 2909.29 and -70.71, and differ from the lines' subtotals. Analysis Propagating the manual tax amounts in `_reduce_base_lines_with_grouping_function` causes a delta amount to be present in `_apply_base_lines_manual_amounts_to_reach` whereas there shouldn't be. Solution Drop manual tax amounts in `_reduce_base_lines_with_grouping_function`. We also take the opportunity to fix the `delta_currency == currency` condition which caused the price_unit to be adjusted twice if the invoice currency is the same as the company currency. opw-5001935
This fixes an issue where older Saudi Phase 1 ZATCA QR codes disappeared after the electronic invoicing module was installed. Invoices now show the correct QR code for either Phase 1 or Phase 2, helping businesses keep compliant invoice information visible.
Original PR description
Phase 1 ZATCA QR codes disappear when l10n_sa_edi is installed, there is a check for document submission to display the QR code for Phase 2 which older Phase 1 invoices will not pass as it doesn't use edi. Description of the issue/feature this PR addresses: Phase 1 ZATCA QR Code disappears once l10n_sa_edi is installed Current behavior before PR: Always hide Phase 1 ZATCA QR Code Desired behaviour after PR is merged: Showing Phase 1 and Phase 2 ZATCA QR codes based on the invoice task-5005304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222627 Forward-Port-Of: odoo/odoo#222285
This fixes an issue where capacity lines could appear to disappear immediately after saving a new storage category, even though they returned after reloading. The change keeps saved relational data consistent during record creation, improving reliability for inventory setup and related workflows.
Original PR description
_Note: The main fix of this PR (the orm one) raised an error in CRM, a test was working thanks to some cache pollution (cf description of crm commit). The below text only shows the description of the…
_Note: The main fix of this PR (the orm one) raised an error in CRM, a test was working thanks to some cache pollution (cf description of crm commit). The below text only shows the description of the orm commit._ The use of a computed inverse o2m field does not correctly work when creating the record of the main model. To reproduce: (Need stock) 1. In Settings, enable "Storage Locations" 2. Create a new Storage Category - Make sure to have one Capacity by Product Error: on save, the Capacity by Product disappears. Yet, if the user reloads the page, the capacity will be back. First, few details about the Storage Category model. We are dealing with the field `product_capacity_ids`, a computed inverse o2m field: https://github.com/odoo/odoo/blob/e5e3a3f7bf3770fe2bba11b501870d4fb7ef2e51/addons/stock/models/stock_storage_category.py#L15 Its content is a subset of the `capacity_ids` field: https://github.com/odoo/odoo/blob/e5e3a3f7bf3770fe2bba11b501870d4fb7ef2e51/addons/stock/models/stock_storage_category.py#L14 So, its compute simply get a subset of `capacity_ids` and its inverse will write some values on `capacity_ids`: https://github.com/odoo/odoo/blob/e5e3a3f7bf3770fe2bba11b501870d4fb7ef2e51/addons/stock/models/stock_storage_category.py#L39-L41 Now, back to the issue. When we `web_save` the category, at some point in the create process, it leads here https://github.com/odoo/odoo/blob/bdb24afbf85f4d58722db493f725dd95c5780ff7/odoo/orm/models.py#L4389-L4408 Where we want to resolve all the pending inverse. To do so, we first update the cache (L4401) and we then call the inverse methods (L4408). In the above case, it means that we first update the value of `product_capacity_ids` in the cache. The value we are passing is a `Command.CREATE` value. In that case, when converting the value for the cache, we actually create a `NewId` record: https://github.com/odoo/odoo/blob/ae55f5b494005a1e7566c819592f7dd64623c3fd/odoo/orm/fields_relational.py#L513-L516 When running the inverse, we write this record on `capacity_ids` (cf the code quoted above). This will lead to the actual creation of the capacity record. But... Here is where the problems begin: we have updated the cache with a `NewId` value and define `capacity_ids` with an existing record. However, we don't update anything in the cache. As a result, at the end of `web_save`, we do a `web_read`. It will lead here: https://github.com/odoo/odoo/blob/bdb24afbf85f4d58722db493f725dd95c5780ff7/odoo/orm/models.py#L3427 Where we convert the value of `product_capacity_ids`. Since available in the cache, we will use the `NewId` value and convert it, i.e.: we will return the `.ids` of the recordset: https://github.com/odoo/odoo/blob/ae55f5b494005a1e7566c819592f7dd64623c3fd/odoo/orm/fields_relational.py#L569-L570 Which means... The actual IDs, excluding the `NewId` one. This explains why the line suddenly disappears on save. Then, reloading the page will trigger the compute based on `capacity_ids`. This field is correctly defined, so will do the compute -> the line will appear. Since we update the cache to compute the inverse, we should then clear that cache to ensure proper consistency with what happened during the inverse. OPW-4915087
Customers could lose the ability to sign a sale order if confirmation failed after they submitted their signature. The change keeps the signature from being permanently saved until the order confirmation succeeds, allowing customers to retry after the underlying issue is resolved.
Original PR description
In this bug, sale order signature is commited before confirm, causing sale order not be able to be signed later, if confirm fails. To reproduce the bug: 1- Create a consumable product with `Buy` and `Dropship` routes enabled in the inventory tab 2- Do not put in any vendors in the purchase tab 3- Create a sale order with this product and uncheck the online payment option. 4- On an incognito browser, sign in as portal user and open the sale order 5- Click on the `Accept & Sign` button and confirm 6- We get an invalid operation error because of not having vendors 7- Reload the order. As you see, it is not possible to sign it To fix the issue, we use flush instead of commit, so when confirm fails it can rollback. Note: It is not easy to write a test for this case, because the `action_confirm` fails in a specific case when `purchase_stock` and `stock_dropshipping` are installed. opw-4864150 Forward-Port-Of: odoo/odoo#223610
Fixes an issue where live chat visitors could incorrectly see a restart button after their conversation was forwarded to a human agent. Chatbot progress and selected answers are now kept consistent across browser tabs, reducing confusion during support conversations.
Original PR description
Before this commit, the restart button was sometimes shown after the conversation was forwarded to an agent which should not happen. This happens because the state of the chat bot is not sent on the bus, leading to inconsistent state. This commit ensures each step is sent on the bus to avoid inconsistencies. This commit also ensures the selected answer of a selection step is properly sent to every tab to avoid similar issues. task-5031990 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
This fixes an issue where electronic credit notes could show a zero price as a negative value when the related line had a negative quantity. The correction helps ensure UBL files, including Romanian CIUS-RO exports, pass validation and are not rejected for invalid pricing.
Original PR description
**Issue description:** When creating a UBL credit note, a line with a zero unit price and a negative quantity would have its gross unit price calculated as `0.0 / <negative_qty>`. This results in a…
**Issue description:** When creating a UBL credit note, a line with a zero unit price and a negative quantity would have its gross unit price calculated as `0.0 / <negative_qty>`. This results in a negative zero `-0.0`, which is considered an invalid negative net price by some EDI validators (e.g., Romanian CIUS-RO), causing the file to be rejected. **Steps to reproduce:** 1. Create a Sales Order with two lines: one product for €100 and a second (e.g., a delivery service) for €0. 2. Create and pay a downpayment invoice for a fixed amount greater than the order total, e.g., €200. 3. Go back to the Sales Order and create a "Regular Invoice". This will generate a credit note with negative quantities on the lines. 4. Ensure the journal is configured for UBL export (e.g., CIUS-RO). 5. Post, then send the credit note and inspect the generated XML file. The zero-priced line will show `cbc:PriceAmount = '-0.0'`. opw-5000314 Forward-Port-Of: odoo/odoo#223643 Forward-Port-Of: odoo/odoo#223074
The manufacturing order overview now calculates bill of materials costs using the correct unit of measure, preventing component quantities from being counted twice. This gives users accurate production cost comparisons when products are manufactured in packs or other non-unit quantities.
Original PR description
Steps to reproduce:
- Create a storable product “P1”:
- UoM: Unit
- BoM:
- Pack of 6 of P1
- Components:
- C1: 6 units (price = $5)
- C2: 6 units (price = $10)
- Create a manufacturing order:
- 1 Pack of 6 of P1
- Confirm the MO
- Go to the MO overview
Issue:
- MO cost = $90 → ($5 * 6) + ($10 * 6) → correct
- BoM cost = $540 → ($5 * 36) + ($10 * 36) → wrong
Cause:
The BoM cost calculation uses `product_uom_qty` (6 units) of the production instead of computing the real quantity needed with the correct UoM.
As a result, component quantities are multiplied twice.
opw-4954953
Forward-Port-Of: odoo/odoo#223730This fix prevents Point of Sale loyalty workflows from failing when a customer record has not yet been loaded. It also makes an automated sales test use a unique customer name, reducing false test failures and improving release stability.
Original PR description
In PoS loyalty when activating a barcode we were not checking if the partner was already loaded in the PoS resulting of an undefined var. Now we check if the partner is loaded before trying to access it. In PoS sale tour, we were creating a partner called "Test Partner" which was already created in the setup, so sometime the tour was selecting the wrong one. Now, the name of this partner is changed to "AAA - Test Partner invoice" Runbot error: 230992, 230995 https://runbot.odoo.com/odoo/runbot.build.error/230992 https://runbot.odoo.com/odoo/runbot.build.error/230995 Forward-Port-Of: odoo/odoo#223618
The Copy Link action now sends public and portal users to the correct page containing the message instead of an unauthorized page. The change also prevents link copying where a user lacks read access, helping avoid accidental exposure of access tokens.
Original PR description
Before this commit, links produced by the "Copy Link" action on portal or public chatters would redirect to an unathorized page. This happens because the route used in the link would check access rights to the message, which public and portal users usually don't have. This commit fixes the issue by overriding the link route in modules with public chatter such that it would redirect to the page containing the chatter. This commit also removes the possibility to copy links of messages inside portal documents for which a user has no read access to avoid leaking the access token. task-4551910 Forward-Port-Of: odoo/odoo#223481 Forward-Port-Of: odoo/odoo#202555
This fixes the setup of two Spanish 0% sales taxes so they are correctly treated as exempt with the proper legal reasons. It also removes older duplicate exempt tax entries that are no longer needed, helping invoices and electronic tax reporting use the right classification.
Original PR description
Currently 2 sales taxes are misconfigured.
They both should be marked as 'exento' ("Exento") instead of 'no_sujeto_loc' ("No Sujeto por reglas de Localization")
- "0% EU G"; with "Exempt Reason" E5 / "Art. 25"
- "0% EX G"; with "Exempt Reason" E2 / "Art. 21"
This commit updated those taxes
Due to this the following sales taxes become obsolete.
- "VAT Exempt (Art. 21)"
- "VAT Exempt (Art. 25)"
They are deleted in this commit.
opw-4850585
Forward-Port-Of: odoo/odoo#223725
Forward-Port-Of: odoo/odoo#223603Partial payment links for invoices now correctly carry over the intended partial amount when customers click Pay. This prevents customers from being asked to pay the full invoice total by mistake, improving payment accuracy and customer experience.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have an unpaid invoice; 2. generate a partial payment link; 3. open partial payment link; 4. click the Pay button. Issue ----- The invoice's full amount gets requested. Cause ----- Commit 5697493e0091 added `amount` as a named keyword parameter in an `_invoice_get_page_view_values` override, but failed to pass it along to the call to `super`. As the base method no longer receives an `amount` parameter, it defaults to the invoice total. Solution -------- Pass `amount` to the `super` call. opw-5013044 Forward-Port-Of: odoo/odoo#223554
A test in the subcontracting dropshipping area now sets the required sender email explicitly, avoiding failures when demo data is not installed. This keeps automated validation reliable without changing customer-facing workflows.
Original PR description
This issue comes from [216633](https://github.com/odoo/odoo/pull/216633) Administrator doesn't have an email address without demo data since [185809](https://github.com/odoo/odoo/pull/185809). This causes an error in no demo build for the test `test_kit_dropshipped_change_qty_SO` because it requires a sender's email address configured. Runbot - [229621](https://runbot.odoo.com/odoo/error/229621) Forward-Port-Of: odoo/odoo#220181
The product feed used for Google Merchant Center now checks for product images in a lighter way. This prevents memory errors when exporting large catalogs, helping merchants keep their product listings available and up to date.
Original PR description
**Traceback:** ```python File "/home/odoo/src/odoo/saas-18.3/addons/website_sale/controllers/gmc.py", line 63, in gmc_data_source 'items': products._prepare_gmc_items(), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^…
**Traceback:**
```python
File "/home/odoo/src/odoo/saas-18.3/addons/website_sale/controllers/gmc.py", line 63, in gmc_data_source
'items': products._prepare_gmc_items(),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/addons/website_sale/models/product_product.py", line 251, in _prepare_gmc_items
**product._prepare_gmc_image_links(base_url),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/addons/website_sale/models/product_product.py", line 281, in _prepare_gmc_image_links
'image_link': urljoin(base_url, self._get_image_1920_url()) if self.image_1920 else '',
^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1495, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields_binary.py", line 137, in compute_value
super().compute_value(records)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1661, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/saas-18.3/addons/mail/models/mail_thread.py", line 468, in _compute_field_value
return super()._compute_field_value(field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 4627, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 73, in determine
return needle(*args)
^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/addons/product/models/product_product.py", line 164, in _compute_image_1920
record.image_1920 = record.image_variant_1920 or record.product_tmpl_id.image_1920
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1458, in __get__
recs._fetch_field(self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 3452, in _fetch_field
self.fetch(fnames)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 3490, in fetch
fetched = self._fetch_query(query, fields_to_fetch)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 3607, in _fetch_query
field.read(fetched)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields_binary.py", line 149, in read
att.res_id: att.datas
^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1495, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields_binary.py", line 137, in compute_value
super().compute_value(records)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1661, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 4627, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 73, in determine
return needle(*args)
^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/addons/base/models/ir_attachment.py", line 229, in _compute_datas
attach.datas = base64.b64encode(attach.raw or b'')
^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1495, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields_binary.py", line 137, in compute_value
super().compute_value(records)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 1661, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 4627, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/saas-18.3/odoo/orm/fields.py", line 73, in determine
return needle(*args)
^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/addons/base/models/ir_attachment.py", line 235, in _compute_raw
attach.raw = attach._file_read(attach.store_fname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-18.3/odoo/addons/base/models/ir_attachment.py", line 118, in _file_read
return f.read()
^^^^^^^^
MemoryError
```
Issue:
-------
Loading product data in Google Merchant Center was causing memory error when handling a large number of products (14k+ in this case). The problem occurred because `self.image_1920` was used to check if a product had an image. This field is computed and non-stored, so accessing it for many records loads the full high-resolution image into memory, leading to excessive memory usage.
Solution:
------------
Use `image_128` instead of `image_1920` for image existence checks, significantly reducing memory usage and preventing the error.
upg-3063427
opw-4981983
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update fixes internal mail-related tests so they pass consistently when an optional file detection library is installed. It helps maintain release quality and reduces false test failures without changing customer-facing behavior.
Original PR description
Those tests are failing when python-magic is installed. Since 26f9c82b99 Odoo > saas-18.4 has this lib as a requirement and comes with appropriate fixes. This commit adapts some test from 17.0 up to saas-18.4 to also work when the python-magic lib is installed. Forward-Port-Of: odoo/odoo#223642 Forward-Port-Of: odoo/odoo#223609
This fix changes how the web test runner handles missing excluded test or suite IDs passed through URLs. It prevents automated Runbot sub-builds from failing repeatedly because of harmless missing IDs, while still surfacing useful information when an included ID cannot be found.
Original PR description
Before this commit, URL test/suite IDs were warned in the console if they didn't match any test/suite registered by the test runner. This is an issue for Runbot which runs sub-builds with the same URL parameters regardless of the installed addons, which repeatedly fails such builds. This commit changes the warning to a regular log, so that these builds stop failing, while still allowing a developer to get the information that an ID has been removed/ignored. runbot [230082](https://runbot.odoo.com/odoo/runbot.build.error/230082) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223242
This fix avoids unnecessary loading of full attachment data when only file size information is needed. It improves responsiveness in views with many images, such as product kanban pages, especially when image storage has higher latency.
Original PR description
Since 7744886d6141ca7971d91807d0444c707e10fdf8, reading binary field with bin_size=True still reads the ir.attachment datas field, which is relatively slow with some storage backends. In the products kanban view this can easily add 1 sec to web_search_read, if there is a 10ms latency when reading images. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223749 Forward-Port-Of: odoo/odoo#221270
Fixes an issue where invoice journal item amounts could be recalculated incorrectly after switching from a foreign currency to the company currency and back before saving. This helps ensure accounting values remain accurate when users adjust invoice currency during entry.
Original PR description
Steps to reproduce: - Enable a foreign currency with rate - Create an invoice in foreign currency - Switch to company currency, then back to foreign currency before saving - Check journal items values Issue: Amount currency and balance have been affected by the currency rate even if the original currency was restored before saving opw-4864994 Forward-Port-Of: odoo/odoo#222870
The Turkish Nilvera e-Dispatch flow now separates the legal delivery customer from the actual delivery address in generated XML files. This improves compliance and accuracy, especially for non-Turkish customers where the customs ZIP code is now used, and prevents XML generation when no delivery address is available.
Original PR description
Behaviour before this commit: - Previously, the picking partner was used for sending both the Delivery Customer and delivery address in the XML. - Secondly, ZIP was used in Delivery Customer regardless of the country of the partner (Turkish or Non-Turkish) Desired behaviour after this commit: - After this commit, the commercial partner of the picking partner will be used for sending the Delivery Customer data and picking partner itself will be used for sending the Delivery Address in the XML. - Additionally, if the commercial partner is non turkish, customs ZIP will be used in the Delivery Customer in the XML. - If the delivery is validated without giving Delivery Address, then the 'Generate e-Dispatch (XML)' button will be hidden. TaskID:4918748 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223563 Forward-Port-Of: odoo/odoo#218096
Employees assigned to a global working schedule were not getting timesheet entries generated for public holidays. This fix includes global schedules in the holiday timesheet process, ensuring those employees receive the expected entries automatically.
Original PR description
_*= project_timesheet_holidays Steps to Reproduce: --------------------------- 1. Create a global working schedule (company should be False). 2. Assign this working schedule to any employee. 3. Create a public time off (for all the working schedule). 4. You will notice that the timesheet entry is not generated for the public holiday for that employee. Issue: ------------------------------- - Employees who use the WS without a company are excluded from timesheet creation. Cause : -------------------------------- - When grouping employees by calendar global WS (with no company) were being excluded. - And the timesheets were not generated due to the check `calendars_dict[calendar_id].company_id != company` when the WS had no company Fix: ------------------ - We will add the domain to include the global WS and and we will check if the the WS has company id then only check the condition. task-4900941 Forward-Port-Of: odoo/odoo#219916
Reconciliation between a customer invoice and a vendor bill now keeps the correct partner on each generated accounting line. This prevents partner ledger and other reports from showing payments under the wrong customer or vendor.
Original PR description
**Steps to reproduce:** - Install account_accountant - Create an invoice ($100) for Customer X - Create a bill ($100) for Vendor Y - From "Customer Invoices" journal in Accounting dashboard, open…
**Steps to reproduce:** - Install account_accountant - Create an invoice ($100) for Customer X - Create a bill ($100) for Vendor Y - From "Customer Invoices" journal in Accounting dashboard, open "Payments Matching" - Select the invoice and the bill - Reconcile them **Issue:** A move is created with 2 lines that will mark both invoice and bill as paid. However, on both created lines, the partner is "Vendor Y", which is wrong as it will generate incorrect reports (e.g. Partner Ledger). One line should have "Vendor Y" as partner and the other line should have "Customer X". This kind of reconciliation is apparently current in India. **Cause:** When reconciling lines from 2 accounts exactly, a transfer from one account to the other one is created. The transfer is made from the account where the absolute amount to move is the lowest. A transfer is made for each partner that has a move being reconciled with the source account. The transfer is crediting (or debiting) the source account and debiting (or crediting) the reconcile account with the same partner. This is working most of the time but it totally ignores all the partners linked to the moves with the reconcile account. **Solution:** Create one line of the transfer with the source account and the partner as before. For the line on the reconcile account, first check if there's one for the same partner, currency and sign (of the amount to transfer). If not, try to find another partner with the same currency and sign. Otherwise, fall back on the same partner as the line on the source account as it was done before. opw-4735147 Forward-Port-Of: odoo/enterprise#92909 Forward-Port-Of: odoo/enterprise#89972
Bank reconciliation now avoids incorrectly matching foreign exchange fees or similar bank charges as partial payments. Payments are matched only when key details align exactly, reducing reconciliation mistakes and helping finance teams process fees correctly.
Original PR description
In case of foreign payment using a bank account in another currency, banks can reflect the foreign currency exchange fee on another bank account belonging to the company and in its main currency. Fr…
In case of foreign payment using a bank account in another currency, banks can reflect the foreign currency exchange fee on another bank account belonging to the company and in its main currency.
Fr example: in a EUR company having in the same bank (e.g ING) both an USD and a EUR account, making a payment using the USD bank account gets you effectively 2 bank transactions while you initiated only one:
- the payment in the USD account and
- the currency diff fee in the EUR account.
In this particular use case, the communication on the currency diff fee reflects the one from the payment and, depending on the reconciliation order, that currency diff could be taken as a partial payment
because we were matching on the words in payment_ref regardless of the currency used, while it shouldn't and must be processed as a bank fee.
The outstanging payments are now only matched when the account.payment memo and the statement line payment_ref exactly match, and if the journal is the same. The algorithm for invoices matching doesn't change except we explictly remove the outstanding accounts from the list of reconcilable accounts to search on.
Previously, a match between an invoice ref and a transaction payment_ref could occure even if the matching word wasn't complete.
E.g: invoice ref: INV/2025/01/10
transaction payment_ref: INV/2025/01/100
To be sure this isn't the case anymore, we check that the matching words are properly surrounded by a "finishing character".
task-5023163After downloading the ADEME emissions database in ESG, users are now taken directly to the emissions factors page instead of remaining on the database screen. The update also adds timing logs to help monitor how long ADEME data retrieval takes.
Original PR description
Steps to reproduce: - go on configuration -> databases in ESG - download the ademe database What's happening: A success message is displayed, but the user stays on the database page. What's expected: The user is redirected towards the factor emissions page Additional fix: Small addition of an extra logger in the ADEME download process to allow checking the time needed to fetch the data from the ADEME website Task [link](https://www.odoo.com/odoo/project/967/tasks/4751902) task-4751902
Portal users can now group their helpdesk tickets by customer without encountering an access error. This improves the support portal experience by keeping ticket views usable for invited customers while respecting existing access permissions.
Original PR description
**Issue:**
When logged in as a portal user, grouping tickets by 'Customer' raises an
access error, as portal user can only read partner records if:
```
[('id', 'child_of', user.commercial_partner_id.id)]
```
As defined in rule here:
https://github.com/odoo/odoo/blob/68a156030c366fbbf6b0841e1e2688a571355bf2/odoo/addons/base/security/base_security.xml#L22-L30
**Steps to reproduce:**
- Navigate a helpdesk team and set tickets to be visible to Invited portal
users and all internal users.
- Add a portal user as a follower to one of the team's tickets.
- Log in as the portal user, navigate to Tickets, and group by Customer.
An access error is raised
opw-4969684
Forward-Port-Of: odoo/enterprise#92603FedEx shipping requests now remove the country prefix from province or state codes when needed. This helps avoid shipment processing errors for locations where standard regional codes include the country code, such as Sweden.
Original PR description
Before this commit: The province code for some countries includes the country code too. FedEx expects a two letter code in the request. For example, the standard code for Stockholms lan is "SE-AB" and the code FedEx expects is "AB". After this commit: The country code is excluded from the province code. opw-4984662 Forward-Port-Of: odoo/enterprise#92650
This fixes an issue where changing a product variant during subscription checkout could apply the selected plan to an outdated dropdown. The update makes the checkout tour more reliable and helps ensure customers see the correct subscription plan selection.
Original PR description
The subscription plan selection gets removed and replaced (static template website_sale_subscription.SubscriptionPricingSelect) So the change of value occurs, but on the wrong select. This was happening as when changing the variant we will replace the plan_select in the widget with another template and since this will happen before the RPC set the plan_id that we are choosing as the default one we will actually have the old select option back on the dom to be selected. https://github.com/odoo/enterprise/blob/82593f9932e92800251d18453b0c73e5ce9b5ec0/website_sale_subscription/static/src/js/variant_mixin.js#L35-L41 We are setting the select option to the old one after replacing it. This commit introduces a delay to prevent the test to fail (which happened most of the time) runbot-error-110627 Forward-Port-Of: odoo/enterprise#86639
This fix ensures Mexican electronic invoices use the same posting time throughout the invoicing and CFDI generation process. It also preserves record locking during sending, reducing the risk of inconsistent invoice data.
Original PR description
`fecha_datetime` could be set to a different value than the `document_post_time` passed as parameter because of the `min`. We also must revert the `_cr.commit` during the sending because it removes the lock on records. Instead we set the invoice post time and commit before locking. task-none Forward-Port-Of: odoo/enterprise#92355
This fix ensures Intrastat export data for one country cannot unintentionally affect another country's localization. It helps keep country-specific trade reporting accurate and reduces the risk of incorrect regulatory submissions.
Original PR description
Previously, it was possible for the _get_exporting_dict_data from a localization to change the data of another localization. Forward-Port-Of: odoo/enterprise#92892 Forward-Port-Of: odoo/enterprise#92830
A failing automated test in the batch payment accounting module was corrected for Python 3.13. This helps keep the accounting test suite reliable across supported Python versions without changing business behavior.
Original PR description
**Issue:** "test_partner_account_batch_payments_with_journal_entry" is failing when executed in a Python 3.13 env. **Cause:** Sorting the account move lines on a tuple doesn't necessarily result in the same order between version 3.13 and previous ones. runbot-230794
Bank statement labels are now handled more safely when matching reconciliation rules. This helps avoid incorrect matches when labels contain special characters such as plus signs, slashes, dots, or asterisks.
Original PR description
This commit will change the way we normalise the label. We now firstly check that the label is a structure reference and if so we don't escape the numbers. Otherwise, we do an escape of the label and the numbers. Escaping the label will allow to avoid case where we use character like * or . that would mess up the match regex. Example: '+++344/0660/16938+++' will be \\+\\+\\+344\\/0660\\/16938\\+\\+\\+ 'This is a test' will be 'This\\ is\\ a\\ test' task-5023114
This update makes an internal automated test pass consistently whether or not an optional file-detection library is installed. It helps keep document accounting quality checks stable across different environments without changing user-facing behavior.
Original PR description
The test `test_embedded_pdf` fails when the magic lib is installed. modified cherry-pick of 22cbdb477 Adapted to work with or without the lib as the lib is not required in version < 19.0. Forward-Port-Of: odoo/enterprise#92791 Forward-Port-Of: odoo/enterprise#92778
The Danish RSU module has been renamed to better match the naming used by other Denmark-related modules. This is a minor consistency fix that helps users and administrators recognize the module more easily.
Original PR description
This commit will edit the name of the module to be consistent with the other denmark modules no task id Forward-Port-Of: odoo/enterprise#92759