Monday, July 28, 2025
25 changes · saas-18.4
Enhancements to existing features
The system now detects additional error states reported by Mettler Toledo scales before sending weight data to the Point of Sale. This helps prevent cashiers from receiving incorrect scale readings when the device is malfunctioning or in an error condition.
Original PR description
This PR adds the detection of different error states of the Mettler Toledo 8217 protocol. When the scale is in an error state we need to make sure that the PoS user doesn't get any wrong scale data sent to the PoS. Related PR: https://github.com/odoo/enterprise/pull/89602 Forward-Port-Of: odoo/odoo#220420 Forward-Port-Of: odoo/odoo#217674
Customers using POS self-order are now taken directly to the next step after a successful payment instead of seeing an extra confirmation screen. This streamlines the checkout experience and reduces unnecessary waiting or taps.
Original PR description
Before: = - A payment confirmation screen used to appear after a successful transaction. After: = - The flow now skips the payment confirmation screen and moves directly to the next Screen. Task: 4836123 Forward-Port-Of: odoo/odoo#213481
Italian e-invoicing can now register an additional identifier, such as a VAT number, so incoming vendor bills are more likely to match the right registered user. This reduces failed invoice matching when suppliers provide only VAT details, improving reliability for Italian accounting workflows.
Original PR description
This improvement addresses an issue in the Italian e-invoicing (l10n_it_edi) and IAP registration logic where incoming vendor bills with only a VAT number failed to match the correct registered EDI user. Changes introduced: - Added `edi_identification_secondary` (e.g. VAT number) to support fallback user matching. - Updated the `/create_user` endpoint to accept and store the secondary identifier. - Modified `create_user` logic to send both primary and secondary IDs from Odoo. - Prepared the base for matching incoming invoices against both identifiers. See also: odoo/iap-apps#1056 Task [link](https://www.odoo.com/odoo/project/967/tasks/4619718) task-4619718 Forward-Port-Of: odoo/odoo#219654 Forward-Port-Of: odoo/odoo#207753
The IoT Box homepage now loads only the information needed for the current view, reducing unnecessary background refreshes. More detailed diagnostic data is fetched only when debug mode is enabled, helping avoid wasted resources from forgotten browser tabs.
Original PR description
On the homepage, we fetch data from the IoT Box every ten seconds, but we always fetch all data, even if we are not using "advanced" mode. The issue is if the homepage stays opened in a forgotten tab, we keep fetching undefinitely, taking resources uselessly. We moved the "advanced mode" to "debug mode" as in Odoo (`?debug=`), and now only fetch displayed data.
This update combines several usability and reliability improvements across Odoo, including better website building blocks, more accurate purchase project costing, corrected Indian time-off access, improved FacturX invoice validation, and better handling of POS discount refunds. It also adds a simple server version endpoint that can help integrations identify the running Odoo version.
Original PR description
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
Users sending invoices to Spanish partners can now choose Factura-e directly from the Send & Print wizard instead of relying only on partner configuration. This makes electronic invoice generation easier to control at send time and helps prevent configuration mistakes.
Original PR description
Currently, `Factura-e` generation is controlled only by an partner E-invoice format setting, making it difficult for users to enable or disable when sending invoices. This PR adds a dedicated Factura-e checkbox on the `Send & Print` wizard for partners in Spain if the `l10n_es_edi_facturae` module is installed. The checkbox defaults to the partner’s current `E-invoice format` but can be toggled by the user. When enabled, it triggers Factura-e file generation and updates the partner’s E-invoice format to ensure consistency. This approach simplifies the user flow and reduces configuration errors. > Task-4831835 Forward-Port-Of: odoo/odoo#214295
The expiration notice now better reflects the timing between the next invoice date and when the database access may expire. This helps customers understand the payment deadline earlier and encourages timely renewal before access is affected.
Original PR description
Previously, the database expiration date was set to the same date as the expiration field, which is now defined as 15 days after the next invoice date. Issue: Users tend to wait until the last minute to pay. This improvement aims to better handle expiration timing and encourage timely payments. TaskID: 4384877 Forward-Port-Of: odoo/enterprise#90931 Forward-Port-Of: odoo/enterprise#90664
Resolved issues and error corrections
Accounting journal sequence prefixes that include Greek letters can now be used without causing invoice confirmation errors. This prevents disruptions for businesses using European communication standards and localized document numbering.
Original PR description
**Issue** Using a Greek letter in the journal's sequence prefix causes a traceback error when confirming an invoice **Steps to Reproduce** 1. Install the Accounting module 2. Navigate to Accounting >…
**Issue** Using a Greek letter in the journal's sequence prefix causes a traceback error when confirming an invoice **Steps to Reproduce** 1. Install the Accounting module 2. Navigate to Accounting > Configuration > Journals 3. Open the Sales journal 4. Under the Advanced Settings tab, set the communication standard to "European" 5. Set the sequence prefix to include Greek letters (e.g., "TΠY") 6. Create and confirm a new invoice 7. Observe the traceback error **Root Cause** The prefix is used in calculating the `check_digits` via a base-36 to base-10 conversion. This conversion fails for Greek characters, which are not valid in base-36, leading to an exception **Fix** Greek letters in the prefix are transliterated to their Latin equivalents before performing the checksum calculation, ensuring compatibility with the base-36 conversion logic Opw-4813790 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#212169
Newsletter signup forms now work correctly when Cloudflare Turnstile is enabled on a website. This prevents page errors and ensures visitors can subscribe without the anti-spam protection breaking the form.
Original PR description
Forward-port of: 10550b3c7ad607576dc48eeba4d601184a2f90d4 Scenario: - configure turnstile in setting - install website_mass_mailing - drop the newsletter widget in any page Result: In saas-18.3 and…
Forward-port of: 10550b3c7ad607576dc48eeba4d601184a2f90d4 Scenario: - configure turnstile in setting - install website_mass_mailing - drop the newsletter widget in any page Result: In saas-18.3 and over, we get this traceback error and the turnstile code is not working: TypeError: Cannot destructure property 'turnStile' of 'odoo.loader.modules.get(...)' as it is undefined. Cause: - On January 2025, in saas-18.2 and over, 421c5e5c4ee6271bb1085b43505cc1c28b2cb574 and 22e777c046521f3f89b62caa5876680beb7f5aba rewrote turnstile - On April 2025, in 17.0 up to master, c48e74f57569a1670fee65d65625488846513d79 uses addTurnstile and addSpinner method and the old file - On April 2025, in saas-18.2 and only saas-18.2, 10550b3c7ad607576dc48eeba4d601184a2f90d4 fixes turnstile for the interaction rewrite So turnstile still cause an error with the newsletter widget in saas-18.3 up to master. Fix: forward-port the saas-18.2 10550b3c7ad607576dc48eeba4d601184a2f90d4 fix in following versions. opw-4925771 opw-4933957 Forward-Port-Of: odoo/odoo#219255
Foreign customers without a state are now correctly treated as overseas customers when creating Indian invoices and sales orders. This prevents them from being assigned the company’s Indian state, helping ensure accurate GST tax treatment and compliance.
Original PR description
Before this PR: When creating invoices/orders for foreign customers that don't have states defined in their country, both **account.move** and **sale.order** models would incorrectly assign the…
Before this PR: When creating invoices/orders for foreign customers that don't have states defined in their country, both **account.move** and **sale.order** models would incorrectly assign the company's Indian state as the place of supply. This happened because the fallback logic would always use **move.company_id.state_id** without checking if the partner was actually Indian. As a result, foreign customers would be treated as Indian customers in GST calculations, leading to incorrect tax treatment and compliance issues. After this PR: Both models now correctly identify foreign customers by checking the partner's country first, before falling back to state-based logic. Foreign customers without states are now properly assigned the foreign state reference (**l10n_in.state_in_oc**) instead of the Indian company's state. This ensures accurate GST treatment where foreign customers are correctly identified as overseas transactions. Task-4900697 Forward-Port-Of: odoo/odoo#220717 Forward-Port-Of: odoo/odoo#216220
This fixes an issue where the same point of sale order could be sent to preparation printers from multiple devices, causing duplicate tickets. The system now checks whether an order was already sent and synchronizes updates after printing, reducing confusion for staff and avoiding repeated preparation work.
Original PR description
Before this change, when a device sent an order in preparation via the ticket printer, this could result in the same order being printed by multiple devices, as the order was not synchronized after it was sent. The error is a bit tricky, because if the user had installed a preparation screen, the order was sent to the preparation screen via syncAllOrders. In this case, the order was correctly synchronized and the other devices were informed of the changes. This commit adds two things. - We check the server before sending the order to preparation to make sure it has not already been sent. - Even when the user does not have a preparation display, the order will be synchronized after being sent to a printer. Forward-Port-Of: odoo/odoo#220716 Forward-Port-Of: odoo/odoo#220535
This fixes an issue where some point-of-sale orders could not be invoiced after session closing when cash rounding was enabled only for cash payments and the order used mixed payment methods. Businesses can now invoice these posted POS orders without accounting imbalance errors.
Original PR description
Before this commit, an imbalance entry error occurred when invoicing a posted order under specific conditions. This issue arose when cash rounding was enabled only for the cash payment method, but the order was paid using both bank and cash. For example, if an order had a total of 12.91, and was partially paid with a bank transfer of 15.59, resulting in a cash return of -2.70, the session could be closed. However, attempting to invoice this order after closing the session would fail due to the imbalance. opw-4912399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218430
This fix helps IoT boxes start correctly when connected to older Odoo versions and reduces early connection failures caused by incorrect device time. It also makes certificate downloading more tolerant of slow networks and prevents Wi-Fi update errors when no IP address is available.
Original PR description
This commit fixes the following issues: - The hw_drivers and hw_posbox_homepage folders were missing from the sparse checkout, meaning that connected to version prior to 18.4 would prevent Odoo from starting. - As the IoT box can only sync time with the network once it gets an internet connection, some early requests could fail due to it thinking the SSL certificates were invalid. We disable verification of the requests to bypass this. - The request to download the certificate for the IoT box only had a timeout of 5 seconds, sometimes this could not be enough so the timeout has been increased to 10 seconds. - Fix an error when calling the `update_wifi` route, caused by `helpers.get_ip()` now being able to return `None`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale invoices now use the bank account configured on the selected payment method when available, instead of always using the company's default partner bank account. This ensures customers receive invoices with the intended payment details and reduces payment routing mistakes.
Original PR description
When generating an invoice for a PoS order we were never using the bank account set on the payment method, but always the one set on the company partner. Steps to reproduce: ------------------- * Create two bank account A and B * Set the bank account A as the company partner bank account * Set the bank account B on any payment method journal * Open PoS and create a new pos_order * Go to the payment screen and check the invoice button * Pay using the payment method linked to bank account B > Observation: The generated invoice will use bank account A Why the fix: ------------ We first try to use the bank account set on the payment method journal if none is present we fallback on the one set on the company partner. opw-4705497 Forward-Port-Of: odoo/odoo#220256 Forward-Port-Of: odoo/odoo#214523
This fixes an issue where customers who paid online through self-ordering could see the same order again as unpaid after the point-of-sale session was reopened. The self-order data is now synchronized with the server so payment status stays accurate across sessions.
Original PR description
If you paid for an order in self-order mode with an online payment method, then close the session and open a new one. The paid order would appear again in the self-order as not paid. Steps to reproduce: ------------------- * Setup a PoS with self-ordering and online payment method. * Open mobile menu and create a new order. * Add a product and pay for the order. * Close the session and open a new one. * Open mobile menu. > Observation: The order you just paid for appears again. Why the fix: ------------ When reading user data from server we should synchronise them with the indexedDB that still contains the old order that is not paid. Note: ---------- I was not able to come up with a test because the indexedDB is not kept between 2 tours. opw-4819672 Forward-Port-Of: odoo/odoo#219258
This fix ensures products with variant options can still be sold in Point of Sale after an attribute line is removed. It prevents valid product combinations from being incorrectly treated as unavailable, reducing sales disruption at checkout and self-ordering points.
Original PR description
Before this commit, removing an attribute line from a product would inadvertently prevent the sale of any combination in the PoS interface. opw-4947529 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219251
Purchase reports now calculate product volume correctly when orders use pack-based units of measure. This ensures reporting reflects the real total volume purchased, improving accuracy for purchasing and inventory analysis.
Original PR description
_______________________________________ ## Short functional explanation of the error When setting the unit of measure as packs, the volume of products aren't computed correctly. ## Reproduction Steps…
_______________________________________ ## Short functional explanation of the error When setting the unit of measure as packs, the volume of products aren't computed correctly. ## Reproduction Steps 1. Go to settings. In the purchase section, click on Units of Measure & Packagings. 2. Click on new, set the unit name as "pack of 4", and set the quantity of the reference unit at 4. Set the reference unit as "units." 3. Go to products and create a test product. 4. In the inventory tab, set the volume greater than 0. 5. Go back to purchase and click on new. Add a line containing the test product, a set quantity, and set as unit "pack of 4." 6. Confirm the order, click on receive then validate. 7. Click on the reporting tab, then purchase. Set the measure as volume and click on the bar chart button. Then, click on the blue column and click on the row corresponding to the purchase operation. ### Expected behavior Let's say we set the product volume as 4 m³, and we purchased one pack of 4. The total volume would be (product volume) * (number of products), which would correspond to 4*4 = 16. ### Unexpected behavior Instead of 16, the total volume shows 1. ## Origin of the issue In the code, the volume is obtained with the operation (product volume) / (number of products) _________________________________________ opw-4871100 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#215605
Sales orders imported into Point of Sale now keep the tax position set on the original order, even when it differs from the customer's default. This helps ensure accurate taxes and pricing at checkout when fulfilling sales orders through PoS.
Original PR description
When a sales order is imported into the PoS, the tax position does not match if the sales order has a different tax position than the one assigned to the partner. This commit ensures that the tax position will always be the one assigned to the sales order and not that of the partner. taskId: 4963118 Forward-Port-Of: odoo/odoo#220709 Forward-Port-Of: odoo/odoo#219869
The point of sale now handles cases where a register session was deleted from another device while a user is still on the opening screen. Instead of showing an error, the screen refreshes so staff can continue working without disruption.
Original PR description
Steps to reproduce: 1. Open a POS session on two devices. Leave both on the opening control screen. 2. On Device 1: - Click Open the Register. - Then click Close the Register. - Click on Backend ( the session is deleted) 3. On Device 2: - Click Open the Register. - This will result in a MissingError. After this commit, the case where the session has been deleted is handled, and the UI is refreshed to ensure the user can continue working without displaying the exception. Retarget of https://github.com/odoo/odoo/pull/218381 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220310
Fixes an error that could stop users from sending multiple invoices at once when the invoice email template used custom recipients. This helps accounting teams complete batch invoice sending reliably without manual workarounds.
Original PR description
Currently, an error occurs when sending invoices in bulk. Steps to Reproduce: - Install the `account` module. - Go to `Email Templates` and open `Invoice: Sending`. - In the `Email Configuration`,…
Currently, an error occurs when sending invoices in bulk. Steps to Reproduce: - Install the `account` module. - Go to `Email Templates` and open `Invoice: Sending`. - In the `Email Configuration`, uncheck `Default Recipients` and enter `demo@gmail.com` in the `cc` field. - Go to `Invoices`. - Select multiple invoices and click `Send`. `KeyError: <NewId origin=33>` This error occurs when sending invoices in bulk. As mentioned in commit https://github.com/odoo/odoo/commit/058d324855a6e2fe3df51386aa153d46419766bf, the issue was introduced in commit https://github.com/odoo/odoo/commit/39d1907d77ca9c88431e7e9dc9e8c938c79a2987, where the _compute_alerts method attempts to set an alert in the wizard. However,since this is a computed field, the wizard record has a NewId and calls the method with a transient record [1]. When trying to access record.id, it returns a NewId [2], and later, when this NewId is used as a res_id [3],it raises a KeyError. [1]-https://github.com/odoo/odoo/blob/aff5f006d5b1996ea3ecc67998067cd0e292cf2a/addons/account/wizard/account_move_send_batch_wizard.py#L63 [2]- https://github.com/odoo/odoo/blob/c70bca77d0447b005b3898e1861facc2828475fc/addons/mail/models/mail_thread.py#L2037 [3]- https://github.com/odoo/odoo/blob/c70bca77d0447b005b3898e1861facc2828475fc/addons/mail/models/mail_thread.py#L2084 This commit fixes the above issue by using move_ids._origin, ensuring that the method is always called with real records, and removes the changes from the previous commit https://github.com/odoo/odoo/commit/058d324855a6e2fe3df51386aa153d46419766bf. sentry-6562659542 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217730
This fix prevents an error from appearing in the restaurant point of sale after a customer completes and pays for a mobile self-order. It improves reliability for restaurants using QR ordering with online payments and preparation printers.
Original PR description
**Configuration:** - Restaurant mode - Self-order mode: "QR + Ordering" - Pay after: "Each order" - Online payment is enabled for self-order **Steps:** - Open the restaurant UI in one tab. - Open the self-order UI in another tab. - Process a self-order with successful online payment. - Switch to the restaurant tab — a server traceback appears. **cause:** - The `notify_synchronisation` method attempted to read POS records with empty record IDs, causing the traceback. **Fix:** - Skip processing records with empty IDs before making server calls. Task-4858105 Forward-Port-Of: odoo/odoo#213500
Orders sent to preparation from a point-of-sale printer are now checked and synchronized so the same order is not printed multiple times across devices. This reduces duplicate kitchen or preparation tickets and helps staff avoid confusion when handling orders.
Original PR description
*: pos_urban_piper_enhancements Before this change, when a device sent an order in preparation via the ticket printer, this could result in the same order being printed by multiple devices, as the order was not synchronized after it was sent. The error is a bit tricky, because if the user had installed a preparation screen, the order was sent to the preparation screen via syncAllOrders. In this case, the order was correctly synchronized and the other devices were informed of the changes. This commit adds two things. - We check the server before sending the order to preparation to make sure it has not already been sent. - Even when the user does not have a preparation display, the order will be synchronized after being sent to a printer. Forward-Port-Of: odoo/enterprise#91093 Forward-Port-Of: odoo/enterprise#91006
Fixes an issue that prevented users from merging duplicate records in the Data Cleaning app after a recent system change. This restores the merge action so deduplication workflows can continue without an unexpected error.
Original PR description
Currently an error occurs when we try to merge data in deduplication. Steps to replicate: - Go to: Data Cleaning > Configuration > Deduplication. - Open any Deduplication Rules > Deduplicate > select…
Currently an error occurs when we try to merge data in deduplication. Steps to replicate: - Go to: Data Cleaning > Configuration > Deduplication. - Open any Deduplication Rules > Deduplicate > select any record (Make sure at least one record is available in list view). - Click `Merge` on top left. Error: `ValueError: invalid literal for int() with base 10: 'NaN'` The error because of a recent [refactor](https://github.com/odoo/odoo/pull/205486) where the data of a `many2one` will be an object rather than an array. (task-[3547961](https://www.odoo.com/odoo/project/49/tasks/3547961)) In `saas-18.3`, `record.data.group_id` (many2one field) was an array, so the line [1] worked perfectly. But starting in `saas-18.4`, after the change, the value became an object instead of an array. Because of that, `record.data.group_id[0]` is now `undefined`, and `parseInt()` returns NaN, which causes the `int()` on line [2] to throw a `ValueError`. [1] - https://github.com/odoo/enterprise/blob/7d020d73762a17386cae4b68c15a5d59a51fb480/data_cleaning/static/src/views/data_merge_list_view.js#L108 [2] - https://github.com/odoo/enterprise/blob/7d020d73762a17386cae4b68c15a5d59a51fb480/data_cleaning/models/data_merge_group.py#L113 The lines that returns object is [this](https://github.com/odoo/odoo/blob/564348a5172ea98b38c903686c21d007d0e57b48/addons/web/static/src/model/relational_model/utils.js#L517-L523). This commit solves the problem by accessing the ID using `.id` instead. sentry-6739344848
Commission calculations now account for subscription transfer logs during renewals, so sales teams receive credit based on the correct recurring plan rates. The update also prevents duplicate achievement lines when no currency is set and improves commission report performance for larger datasets.
Original PR description
PURPOSE In order to take into account the achievement rate based on recurring plan for MRR log on a renewal, we need to take into account transfer logs SPECIFICATIONS Take into account transfer logs…
PURPOSE
In order to take into account the achievement rate based on recurring plan for MRR log on a renewal, we need to take into account transfer logs
SPECIFICATIONS
Take into account transfer logs in achievements computation. Source should be clear that it's a transfer log of a renewal
Example:
If you have a Monthly sub to 100$/month but the yearly of 1000/year (MRR = 83.33) With a commission plan rewarding: 80% MRR of Monthly and 100% MRR of yearly
If you renew a montlhy into a yearly --> MRR that was 100 become 83,33 so you have a negative MRR so a negative commission and a negative on yearly so with more weight (100% instead of 80)
Current:
Renew in into yearly: 100% of MRR change -16.67 = -$16.67
New monthly 80% of MRR change $100 = $80
Total = 63.33 (modifié)
New
New monthly 80% of MRR change $100 = $80
Transfer 1 : 80% of MRR change -100 = -$80
Transfer 2 : 100% of MRR change +100 = +$100
Contraction of MRR: 100% of MRR change -16.67 = -$16.67
Total = 83.33
Moreover this PR:
- fix a bug when achievements were duplicated when no currency was set.
- improve performances by creating a temporary table for invoice rules.
taskid-4783929
Forward-Port-Of: odoo/enterprise#88646Fixes an issue in Odoo Sign where radio button groups lost their mutual selection behavior when a template layout was reused on a new document. This preserves the intended signing experience and prevents recipients from selecting multiple options in what should be a single-choice group.
Original PR description
If applied, this commit will make so that when a user uses the layout of a template document on a new document, the radio buttons will stay linked.…
If applied, this commit will make so that when a user uses the layout of a template document on a new document, the radio buttons will stay linked. _____________________________________________________ Using the layout of a template document, containing radio buttons, on a new document will unlink radio buttons, making them useless. 1. Go to the Sign module, and click on the Templates tab. 2. Click on the "Upload PDF" purple button, and upload a PDF of your choice. 3. On the left side of the screen, there's a panel where we can drag and drop sign items. Drag and drop a Radio button. 2 buttons will automatically show, and a yellow link will appear between the buttons. This link indicates that, when a user opens the document to sign, when clicking on a radio button, the other one will automatically be unselected if previously selected. 4. Save and return to the Templates window. 5. A new row has appeared with the name of the document. On the right side of this row, hover the house next to the share button and click on the 3 dots. Then, click on Use Layout. 6. Upload a PDF of your choice. 7. When the PDF shows, there's no yellow link between the radio buttons, unlike on the template from which the layout was used. In the file sign/models/sign_document.py, in the method _copy_sign_items_to(self, new_document), we copy every sign item from the template to the new document. However, the copy method we call doesn't take into consideration the special link between radio buttons, replicating the buttons correctly but not the link. This link is expressed by the radio set to which the radio buttons belong: indeed, after the copy of sign items, each radio button belongs to a different radio set, separating them. ### Explanation of the fix The fix consists of a rework of the _copy_sign_items_to method and a brand-new method specifically used to copy radio buttons. To keep the link between them, we assign all the buttons of the same set on the original documents to the same brand new radio set. The first button is copied normally: this creates a new radio set. Then, for the remaining buttons, we call copy_radio_item, to which we pass the button created first to use the information the next buttons will share with it. ______________________________________________________________ opw-4842590 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#87536