Friday, August 22, 2025
24 changes · saas-18.3
New functionality added to Odoo
The Adam Equipment scale driver is no longer enabled by default on IoT boxes and is now provided through a separate Point of Sale option. This prevents unrelated serial devices from being incorrectly treated as scales, reducing setup confusion for customers, especially around fiscal devices.
Original PR description
Community PR: https://github.com/odoo/odoo/pull/223687 Backport of https://github.com/odoo/odoo/pull/221326, note that in stable the new module WILL NOT be installed automatically, meaning if someone…
Community PR: https://github.com/odoo/odoo/pull/223687 Backport of https://github.com/odoo/odoo/pull/221326, note that in stable the new module WILL NOT be installed automatically, meaning if someone is using an Adam scale it will break if their IoT box restarts. It was chosen to proceed anyways as it is unlikely anyone is using this setup in 18.3, and if they are it can be fixed by installing the module manually. Before this commit, the Adam Equipment serial scale driver was included by default on the IoT box. However, this causes issues as there is no way to detect the presence of one of these scales automatically. This caused any unidentified serial device to be registered as an Adam scale, leading to much confusion with customers, especially regarding setting up an FDM. After this commit, the Adam driver is moved into its own module, and a checkbox added to the PoS settings to enable it. This way, only customers who actually need the driver will get it, and everyone else can benefit from not having it wrongly detect devices. task-4954021
Adds support for Swedish BBAN, Bankgiro, and Plusgiro payments, including XML export files for bank processing. This helps Swedish businesses handle local payment formats directly in Odoo with fewer manual steps.
Original PR description
Enable generic Swedish BBAN and Bankgiro/Plusgiro payments and xml exports. Task: 3814018 Forward-Port-Of: odoo/enterprise#92584 Forward-Port-Of: odoo/enterprise#87850
Enhancements to existing features
Manufacturing work orders can now be completed much faster when many are confirmed at once. This reduces waiting time for production teams, especially when several work orders belong to the same manufacturing order.
Original PR description
### Description: Improves the performance of `button_finish` when confirming many work orders. Previously, the method would update each work order individually, leading to slow performance. This PR changes the way the write is executed to do it by batch, which is much faster, especially when work orders share the same manufacturing order. ### Benchmark (in 18.0): | N° of work orders | Before | After | |-------------------|--------|-------| | 250 | 14s | 610ms | | 500 | 53s | 1s | ### Reference: opw-4957774 Forward-Port-Of: odoo/odoo#223588
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
Features or functions removed from Odoo
The IoT box will no longer include the Adam scale driver by default because it was incorrectly identifying many serial devices as Adam scales. This reduces device confusion for customers, but users who rely on Adam scales may need to install the separate driver module manually after an IoT box restart.
Original PR description
Enterprise PR: https://github.com/odoo/enterprise/pull/92824 Backport of https://github.com/odoo/odoo/pull/221326, note that in stable the new module WILL NOT be installed automatically, meaning if someone is using an Adam scale it will break if their IoT box restarts. It was chosen to proceed anyways as it is unlikely anyone is using this setup in 18.3, and if they are it can be fixed by installing the module manually. The Adam scale driver causes many issues due to it detecting any serial device as an Adam scale, as there is no way to identify them automatically. This causes much confusion for clients, as their devices are wrongly appearing as an Adam scale. This commit removes the driver from the IoT box by default. It is being moved into a separate module in the associated Enterprise PR. task-4954021 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
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 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
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 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-5023163Portal 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#92603This 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