Daily updates from Odoo
Wednesday, July 1, 2026
374 changes
21 changes
Enhancements to existing features
When users compare report lines against selected lines, the comparison is always shown as a percentage. This update hides the Amount/Percent selector in that case, reducing confusion and simplifying the report setup.
Original PR description
In [^1] support for comparison against user selected lines was added. This is always in percentages, as such, the "Comparison In" option that was added in [^2] is not useful as we would never set it to Amount. In this PR we hide "Comparison In" if the report line is selected. task-6322616 [^1]: odoo/enterprise#116721 [^2]: odoo/enterprise#116480
Resolved issues and error corrections
This change removes an unnecessary half-second delay from Discuss-related automated tests, making them run much faster again. It restores test performance to previous levels, which helps developers get quicker feedback and reduces wait time in the test pipeline.
Original PR description
Before this commit, discuss tests were very slow. This is a consequence from PR that adds waitUntilSubscribe to mail test helpers's start() [1], for which the wait UntilSubscribe takes about 500ms to resolve. Because of this, tests that take about 200ms were taking 700ms instead. "mail > activity" test suite was taking about 3 sec. but now takes 21sec, so a 700% time increase. The root cause comes from Websocket that has `OUTGOING_BATCH_DELAY` that is at 500ms, which also takes into account the initial sendToServer, therefore the tests using the mail test helpers always had this 500ms delay. This commit fixes the issue by mocking `OUTGOING_BATCH_DELAY` to `0`, so this is basically instantaneous. Tests are back to their prior speed, and activity tests are back to 3 sec., down from 21 sec. [1]: https://github.com/odoo/odoo/issues/270281
This change fixes an unreliable test around retrying message loading in the chat interface. It ensures the test waits for the first loading attempt to be fully in progress before retrying, which better matches real user behavior and prevents false failures in automated checks.
Original PR description
The "Retry loading more messages on failed load more messages" test drove load-more by scrolling (real IntersectionObserver) and failed the fetch synchronously, then clicked retry immediately. The observer could fire the older-fetch twice and leave a second fetch in flight at the retry click, which then no-op'd (fetchMoreMessages bails while a fetch is loading), leaving 30 messages instead of 60. This is a test-timing artifact: a real user retries long after any fetch has settled. Fail the load-more through a Deferred rejected only once the fetch is in flight, like jump_to_present.test.js. While it is pending, duplicate observer fires no-op, so no orphan fetch can race the retry. https://runbot.odoo.com/odoo/error/242113 Forward-Port-Of: odoo/odoo#272942 Forward-Port-Of: odoo/odoo#272430
This change updates the subcontracting landed costs module to depend on the correct related module. It reduces the risk of broken behavior if one of the connected modules is removed, helping keep the feature more reliable.
Original PR description
`mrp_subcontracting_landed_costs` uses template from `mrp_landed_costs` but doesn't depends on it, but rather it's ancestry `stock_landed_costs`. While the module are auto-installed, this could raise issues if the module is uninstalled. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When printing a report, the printer selection popup now correctly respects the printers assigned to the user or document. This prevents users from seeing irrelevant printers and helps ensure reports are sent to the intended device.
Original PR description
This commit fixes the domain for the printer selection popup when printing a report. The assigned printers were not taken into account. task-6332442
This update fixes an error that could appear when opening the sales order line list in a custom order extension flow. It restores a required product field so the screen loads correctly and users can continue working without interruption.
Original PR description
- Description of the issue/feature this PR addresses: - The mandatory product_id field required by the many2one_uom widget was omitted from the list view, causing the issue. - The issue occurred when…
- Description of the issue/feature this PR addresses:
- The mandatory product_id field required by the many2one_uom widget was omitted from the list view, causing the issue.
- The issue occurred when the customized 'Extend Order' button was clicked, opening the wizard with all sales order lines loaded into its one2many field.
- Error message: UncaughtPromiseError > OwlError
Uncaught Promise > An error occured in the owl lifecycle (see this Error's "cause" property)
Occured on apollohomecare-migration-v19-33341368.dev.odoo.com on 2026-06-26 10:18:38 GMT
OwlError: An error occured in the owl lifecycle (see this Error's "cause" property)
Error: An error occured in the owl lifecycle (see this Error's "cause" property)
Caused by: Error: The widget 'Many2OneUomField' (field 'product_uom_id') needs a 'product.product' or 'product.template' field. 'product_id' is used but is related to 'undefined' model.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272417Internal notes in Point of Sale now keep the original colors of tagged labels instead of forcing them all to use the same background. This makes colored tags easier to recognize and improves readability, especially in light mode.
Original PR description
Before this commit: ===================== The internal note styling applied a custom background color to all tags, overriding the colors provided by TagsList (o_tag_color_*). As a result, colored tags were displayed with the default background in light mode. After this commit: ====================== The custom background color is applied only to default tags, while tags with an explicit color keep their original TagsList styling. Additionally, demo internal notes were updated with color values to showcase the colored tag behavior. Task:6294250 Forward-Port-Of: odoo/odoo#269746
This update fixes certificate loading so that all certificates in a PEM chain are imported, not just the first one. It helps keep certificate-based workflows complete and compatible, reducing the risk of failures in setups that rely on the full chain.
Original PR description
Previously, only the leaf certificate was parsed when loading PEM-encoded data, ignoring any additional certificates in the chain. This change updates the loading logic to include the full certificate chain, ensuring proper integrity and compatibility with flows that require it. Useful for this PR: odoo/odoo#254906 Task [link](https://www.odoo.com/odoo/project.task/6053921) task-6053921 Forward-Port-Of: odoo/odoo#270037 Forward-Port-Of: odoo/odoo#255100
This change prevents an access error when a user opens a shift that has conflicts they are not allowed to see. Conflict warnings are now only shown to Planning Administrators, which avoids interruptions for regular users.
Original PR description
Steps to reproduce: - Create a shift assigned to resources A and B - Create another overlapping shift assigned only to resource B - Login as resource A with internal user access only - Open the first shift Issue: An access error is raised when opening the shift. Cause: The conflict computation fetches overlapping shifts using SQL, which can return shifts that are not accessible to the current user. Solution: Return empty conflict values for users without Planning Administrator access, as conflict warnings are only available to planning managers. task-6313628 Forward-Port-Of: odoo/enterprise#121465
The Planning / Timesheets Analysis report has been corrected so that slots linked to duration-based calendars are properly counted. This ensures scheduled work appears in reporting as expected, improving the accuracy of planning and timesheet analysis for users.
Original PR description
Issue: ---------------------------------------- The Planning / Timesheets Analysis report doesn't include most of the planning slots if they have a calendar based on duration. Steps to reproduce:…
Issue: ---------------------------------------- The Planning / Timesheets Analysis report doesn't include most of the planning slots if they have a calendar based on duration. Steps to reproduce: ---------------------------------------- - Have a 1 day planning slot (8h-17h) for an employee with a calendar based on duration. - Planning > Reporting > Planning / Timesheets Analysis - The slot is not included in the report Cause: ---------------------------------------- The update of how calendars work in saas-19.2 included the `duration_based` option but the query was not adapted. It still checks if the slot start time is lower than the calendar end time on that day: ```sql F.start_datetime < (d.date::date + (A.hour_to || ' hour')::interval) AND F.end_datetime > (d.date::date + (A.hour_from || ' hour')::interval) ``` But for duration-based calendars `hour_from` and `hour_to` are stored as `0.0`. So `F.start_datetime < (d.date::date + (A.hour_to || ' hour')::interval)` evaluates to False. Solution: ---------------------------------------- If the calendar has `duration_based` to True we only check the date. opw-6217643 Forward-Port-Of: odoo/enterprise#118133
This fix prevents the restaurant setup flow from creating the same Belgian 'Take out' fiscal position and tax more than once when a company branch uses the POS restaurant scenario. As a result, branches can be created successfully without running into errors caused by duplicate tax definitions.
Original PR description
When creating a restaurant with the POS scenario on a company with the Belgian accounting package, we automatically create a new 'Take out' fiscal position and a 'Take out' 6% tax. But when creating a branch for the company and using the same scenario, it will duplicate the 'Take out' fiscal position, and then fail to create because it will try to create a duplicate Tax with the same name and then odoo will complain. After the fix the scenario checks whether the fiscal position and tax already exist on the company, and if they do, it doesn't recreate them. This should let branches use the scenario and then they can use the already existing taxes and FPs. Task [link](https://www.odoo.com/odoo/project.task/5502948) Task-5502948 Forward-Port-Of: odoo/odoo#245848
When a signing template is duplicated, its roles are now copied too instead of being shared between templates. This prevents changes made to one template, such as assigning a person to a role, from affecting another template by accident.
Original PR description
When duplicating a sign template, its sign items were copied but their `responsible_id` was kept as a reference to the same `sign.item.role` records. As a result, editing a role on one template (e.g. assigning a partner through `assign_to`) leaked to the other template sharing it. Copy the role when copying a sign item so each template owns its own roles. task-6288951 Forward-Port-Of: odoo/enterprise#121411 Forward-Port-Of: odoo/enterprise#119864
This update adjusts an automated test for Mexican electronic invoicing so it works correctly whether the Accounting app is installed or not. It prevents test failures caused by a payment moving from “paid” to “in payment” in setups with accounting enabled.
Original PR description
If accountant is installed, payment state of unreconciled payment switch from 'paid' to 'in_payment'. Not having accountant break the test. runbot-939445 Forward-Port-Of: odoo/enterprise#121113
This change prevents stock quantity and replenishment actions from breaking when a product template has dynamic attributes but no created variant yet. It hides the forecasted quantity shortcut in that case and avoids incorrect behavior in related stock flows, helping users manage products more reliably.
Original PR description
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1-…
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1- Create a dynamic attribute with values. 2- Create a product and without saving: - Enable track inventory. - Add the dynamic attributes and values. 3- Save the product. 4- Click on forecasted quantity smart button: - There is a traceback. 5- Click on Replenish: - Unexpected behavior. 6- Click on `Product On Hand Quantity`: - No product will be shown if you try to add quantity. Cause: --- This is caused because there is no variant created. In the steps, if you save the template once before adding dynamic attributes, a single variant will be created which allows it to work without issue. Fix: --- we can fix the TB by hiding the forecasted qty smart button, when there is no variant. However, there will be still issue with `Replenish` flow, which requires a variant. We could do the prevent the issue by ensuring there is at least one variant. opw-6260253 Forward-Port-Of: odoo/odoo#272943 Forward-Port-Of: odoo/odoo#268879
This update keeps split payments in sync with the original order in POS Restaurant when Germany Fiskaly is enabled. It prevents already paid items from staying visible on the parent order, so staff cannot accidentally charge the same items multiple times from the Orders view.
Original PR description
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid…
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid in previous splits. Functionally, the cashier can keep splitting and paying the same line again and again because the parent draft order is not updated consistently in that path. Steps to reproduce: ------------------- * Enable POS Restaurant with l10n_de Fiskaly * Create a table order (e.g. 3 meals + 3 drinks) * Open Split Bill, move 1 meal + 1 drink, and pay * From Orders tab, open the remaining parent order and repeat split + pay * Reopen the parent order from Orders tab > Observation: The parent order still contains quantities that were already split/paid, so the same items can be paid multiple times from the Orders tab. Why the fix: ------------ The Fiskaly `syncAllOrders` override diverged from core sync behavior in the split flow: it ignored explicit `options.orders` and did not await transaction creation for inactive transactions. In the split-bill path this could skip or desynchronize parent-order updates, leaving stale quantities on the parent order. The fix restores expected sync semantics by honoring `options.orders` and awaiting transaction creation before deciding sync eligibility. opw-6175880 Forward-Port-Of: odoo/enterprise#117206
Previously, using the test print option for an Obox POS printer produced no output. This fix makes Obox printers print a test receipt, matching the behavior already available for ePOS printers and helping users verify their setup quickly.
Original PR description
See: https://github.com/odoo/obox/pull/200 Before this commit, attempting to perform a test print for an Obox POS printer would do nothing. After this commit, a test receipt will be printed for the Obox printer just like for ePOS printers. task-6330857
This update ensures test chat messages always have a posting date, so displayed times are consistent during automated testing. It prevents occasional failures where the time shown on a notification could shift by a minute while the test was running.
Original PR description
The hoot test "display the notification message's posting date and time" flakes on loaded runbots: the asserted time ("1:00 PM") sometimes renders a minute later, so the exact :text() match fails.
NotificationMessage shows dateSimpleWithDay, which falls back to the live DateTime.now() when the message has no date. The JS test mock mail.message never defaulted date: the Python fields.Datetime.now default cannot transfer to the mock, so it resolved to false, unlike the real model. hoot's mocked clock is not frozen: now() advances with real wall-clock time, so a slow render drifts past the posting minute.
Default date on the mock so the message carries a posting time, and read that written date back in the tests instead of hardcoding the displayed time: the mocked clock can still advance between mockDate and the (async) create. This covers the six tests that assert a NotificationMessage time.
https://runbot.odoo.com/odoo/error/941202This update fixes an issue in the editor where closing a color popover by clicking back into the page could unexpectedly reset the selected text. As a result, text formatting now behaves more reliably and consistently across browsers, including Chrome and Firefox.
Original PR description
When a popover is used on top of an iframe, when clicking outside the popover but inside the iframe to close the popover, the click away is detected through a blur event. The close during the click…
When a popover is used on top of an iframe, when clicking outside the popover but inside the iframe to close the popover, the click away is detected through a blur event. The close during the click away is used by some features to apply the change. Setting the text color in the editor might modify the DOM structure and therefore needs to readjust the selection to match the new DOM nodes. When confirming a color, or when applying intermediary changes this behavior is required. But when the color confirmation happens because of a click away, this selection gets on the way of the selection made by clicking away. The sequence of events is as follows: - pointerdown in iframe: sets the selection based on the click - main window blur: color gets applied, and selection gets reset - pointermove in iframe: expands selection to new position This commit avoids this unwanted reset by detecting the click away through a pointerdown on the iframe - thus making the selection adjustment before the default browser handling of the event actually sets the selection on the clicked position. Steps to reproduce: - Edit a website page - Drop a text snippet - Select a word - Set a custom color using the color area - so that the color picker remains open - Click (and hold) in the empty area after the text paragraph - Move pointer by a few pixels => The text anchor remained the one of the former selection, but the focus was set according to the pointer position Note that Firefox did not blur the main window, therefore this change actually also unifies the behavior of Chrome and Firefox. The discrepancy between Chrome and Firefox's handling of the blur event in this situation seems to be related to either prioritizing the DOM specifications or the HTML specifications - and the way the are interpreted. The DOM Standard [1] relies on UIEvents [2] which states: "A user agent MUST dispatch this event when an event target loses focus." The HTML Standard defines how to compute the focus [3] and relies on nested browsing contexts [4]. Typically, the simpler readable description for developers says: "document.hasFocus() Returns true if key events are being routed through or to document; otherwise, returns false. Roughly speaking, this corresponds to document, or a document nested inside document, being focused." [1]: https://dom.spec.whatwg.org/#biblio-uievents [2]: https://w3c.github.io/uievents/#event-type-blur [3]: https://html.spec.whatwg.org/multipage/interaction.html#focus-processing-model [4]: https://html.spec.whatwg.org/multipage/document-sequences.html#nested-browsing-contexts task-6268573 Forward-Port-Of: odoo/odoo#269742
This update ensures Romania-specific stock batch logic is applied only when it should be, instead of affecting all cases. It prevents test and automation failures and keeps the standard stock process stable for other setups.
Original PR description
The Romanian specifics were applied without condition which caused runbot errors. Note that this was revealed later on (saas-19.3) after a change in the generic stock test setup. runbot-241098 Forward-Port-Of: odoo/odoo#271985
Financial budgets can now include accounts marked as Other Expenses when users add budget lines. This fixes a selection issue that previously prevented some valid profit-and-loss accounts from being used in budget planning.
Original PR description
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and…
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and create a new account with `Type: Other Expenses`. - Go to Accounting > Configuration > Financial Budgets. - Create a new budget and add a budget line. - Try to select the newly created account. **Observation:** Accounts with the `Other Expenses` type are not available for selection in budget lines. **Root Cause:** At [1], the `expense_other` account type is missing from the `account_id` domain. **Expected Behavior:** Financial budgets should allow all Profit & Loss accounts, since the feature relies on P&L reporting. **Reference**: https://www.odoo.com/odoo/project/49/tasks/4314709 **Fix:** This commit ensures that users can add `Other Expenses` accounts to budget lines. [1]: https://github.com/odoo/enterprise/blob/41b66ba081f3938f7e55da209506c637850ae4ec/account_reports/models/budget.py#L114-L120 opw-6313835 Forward-Port-Of: odoo/enterprise#121735
This update corrects how half-day time off is calculated in the French leave localization. It ensures employees on different working schedules get the expected leave duration, avoiding cases where a full day of leave was incorrectly counted as less than one day.
Original PR description
**Steps to reproduce** - Use a french company with `l10n_fr_hr_holidays` installed - Change the duration type of the time off type set as the "Company Paid Time Off Type" in the French Time Off…
**Steps to reproduce** - Use a french company with `l10n_fr_hr_holidays` installed - Change the duration type of the time off type set as the "Company Paid Time Off Type" in the French Time Off Localization settings to "Half-Day" - Company Working Schedule: - Attendance on a day from 10 to 19, Day Period: Full Day - Part-time employee Working Schedule: - Attendance on the same day from 11 to 12, Day Period: Morning - Attendance on the same day from 13 to 19, Day Period: Afternoon - Create a full day time off for the part time employee on that day, using the time off type set as the "Company Paid Time Off Type" (start am, end pm) -> Excepted: time off duration is 1 day -> Actual: time off duration is 0.89 day **Change** Now that `request_unit_half` of a leave is a simple related to the `request_unit` of the leave type, it becomes important to not rely on a call to `_get_durations` using the company's calendar to compute the leave's duration, as it may not be fully accurate when the company's working hours and employee's working hours are not aligned. Continuation of 05e71eb206eb02a8d15708e6fb532a732a767d6d `_get_fr_date_from_to` is also adapted to take into account multi-day leaves ending in the morning while the employee works in the afternoon (in which case it should not be extended in case the employee doesn't work the next day). opw-6000011 Forward-Port-Of: odoo/odoo#272830 Forward-Port-Of: odoo/odoo#253059
11 changes
Enhancements to existing features
This update makes Odoo’s logging easier to customize, including support for structured log formats and external logging handlers. It helps teams route, filter, and store logs in ways that better fit their operations, without changing normal logging behavior by default.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
Resolved issues and error corrections
Selling combo products in Kenyan Point of Sale now works correctly with eTIMS. The system no longer treats the combo header as a separately registered item, so users will not see a blocking warning when only the items inside the combo are registered.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#122179 Forward-Port-Of: odoo/enterprise#119362
This fix prevents payroll calculations from crashing when the expected student wage salary scale cannot be found. Instead of failing, the system now handles the missing value safely so payroll processing can continue normally.
Original PR description
When computing _get_student_min_wage and the specific salary scale is not found, it returns None and then fails in the tuple compression as None is not an interable. task-6318004
This update prevents the Point of Sale from crashing when Adyen sends repeated payment notifications for the same transaction. It ensures duplicate messages are safely ignored so payments continue to complete normally without interrupting the cashier experience.
Original PR description
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers…
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers webhook notifications at-least-once, so the ADYEN_LATEST_RESPONSE event can fire several times for a single payment, running handleAdyenStatusResponse concurrently. After the await on get_latest_adyen_status, a previous (duplicate) notification may already have resolved the payment line, so getPendingPaymentLine no longer returns it and the subsequent line.uuid dereference crashes. opw-6237987 patched the same root cause on a single line by adding an optional chaining operator in isPaymentSuccessful, which only moved the crash to the next dereference. Fetch the pending line once at the start of handleAdyenStatusResponse and bail out when it is gone, so every dereference below is safe. The same guard is added to the remaining branches of _adyen_handle_response for consistency with the existing Reject branch. opw-6237987 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271181 Forward-Port-Of: odoo/odoo#269720
Images given a device-style shape will now be cropped to match that shape instead of being forced into a square first. This reduces unnecessary cropping and preserves more of the original image, especially for tall or narrow images.
Original PR description
Scenario: - insert image with ~ 1:2 ratio (height bigger than width) - set shape "iPhone `#2`" to that image Result: the image should fit without much cropping the 0.46:1 aspect ratio of the shape, but it is cropped 1:1 before being applied to it. Cause: when the image has a set aspect ratio, we are always cropping it to 1:1 aspect ratio in postProcessCroppedCanvas but it should be cropped to the shape aspect ratio as it was done in previous version. Fix: go back to what was done in saas-18.3 and apply the shape aspect ratio and not just square (1:1) aspect ratio. opw-5415137 Forward-Port-Of: odoo/odoo#250922
When a business card is scanned, the contact’s city is now captured along with the other details. This makes scanned contact records more complete and reduces the need for manual edits.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
This change fixes an issue where the portal homepage flow could get stuck during testing because the page was not fully ready before the next step ran. It helps ensure the portal experience loads reliably and prevents test timeouts.
Original PR description
Since #256698, the `undeterministicTour_doNotCopy` flag was removed. Without this artificial delay, the `portal_load_homepage` tour executes steps faster than the website frontend JavaScript can finish initializing and binding event handlers to the form. Leaving the tour stuck on a blank text screen after Saving and causing a script timeout. Fix this by ensuring the frontend framework is fully initialized before interacting with the form fields. [Runbot-242298](https://runbot.odoo.com/odoo/runbot.build.error/242298) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue where completed documents signed through eMSigner could be downloaded as the original uploaded file instead of the signed version. This ensures customers now receive the final signed PDF after the signing process finishes.
Original PR description
Version: - saas-19.3 Steps to reproduce: - Create a sign request using the eMSigner authentication method. - Complete the signing process. - Download the completed document. Issue: - Users received the original uploaded PDF instead of the signed PDF after completing the signing process through eMSigner. Cause: - After the BinaryValue migration, the completed document was initialized with the original document (document.raw) and only replaced with the eMSigner response for large compressed files. As a result, non-compressed responses stored the original document instead of the signed PDF returned by eMSigner. Fix: - Always use the signed document returned by eMSigner (decrypted_data) to create the completed document. Decode the base64 response and, for large files, decompress it before storing it as binary content. task-6329040
Importing product categories could fail when the parent category name appeared more than once in the system, causing a blocking warning during import. This fix makes category imports work more reliably, so users can bring in category data without unnecessary import errors.
Original PR description
When trying to import Product Categories, importing the Parent Category may raise blocking warnings. Steps to reproduce: - Open Sales > configuration > Categories - Import records - Select a file containing the parent category name - Import category name and parent category Issue: A warning will raise Found multiple matches for value "Furniture" in field "Parent Category" (2 matches) It occurs because, while searching by name, the system will use the complete name of the category so it will match multiple times the same name. This behaviour has been introduced in https://github.com/odoo/odoo/pull/236067/changes/0f788b8105c715681d67fdac04fa82c4c4d48e5e opw-6283004 Forward-Port-Of: odoo/odoo#271862
This fix ensures payroll payruns use the company the user selected, instead of incorrectly falling back to the main company. It prevents blocking warnings during payrun creation for branch companies, including the Hong Kong localization.
Original PR description
[FIX] hr_payroll: fix correct company selection in payrun (branch case) Bug reproduc: 1 - Select 19.3 or master -> Open a branch to belgium company -> create an employee in that branch 2 - In your…
[FIX] hr_payroll: fix correct company selection in payrun (branch case)
Bug reproduc:
1 - Select 19.3 or master -> Open a branch to belgium company -> create an employee in that branch
2 - In your env, select both belgium and its branch, payroll->payrun->select branch as a company.
3 - Continue till the end of payrun creation, you will get warning (blocked) due to wrong company selection, main belg company is selected instead of branch
Bug cause:
1 - In selectEmployees function of hr_payslip_run_form, in the raw_record the company_id is passed as integer.
2 - In buildRawRecord function of hr_version_list_controller, we are assigning company_id as raw_record's company_ids id, but company id was already integer, company_id.id is undefined
3 - Since undefined is passed to the company_id, it uses the self.env.company_id as a default in the creation of hr payrun that cause to the error.
Bug fix:
1 - In the buildRawRecord function of hr_version_list_controller, I just assigned the company_id because it is already integer and all problem is solved.
task - 6326117Invoices in Saudi Arabia and the UAE will now show the invoice title in the customer’s language instead of always defaulting to English. This improves the clarity and professionalism of printed invoices for Arabic-speaking customers.
Original PR description
### Issue: On invoices in SA and AE, the invoice title was always rendered in English even when the customer's language is Arabic ### Cause: In 19.2, the report view `report_invoice_document` was…
### Issue: On invoices in SA and AE, the invoice title was always rendered in English even when the customer's language is Arabic ### Cause: In 19.2, the report view `report_invoice_document` was refactored to require `t-set` declarations before `t-call` In 19.1, `o` was reassigned early with the customer language via `t-value="o.with_context(lang=lang)"`, so all subsequent calls on `o` inherited the correct language https://github.com/odoo/odoo/blob/3d2d8cc498a56faac31e95fb854a94e4011d812d/addons/account/views/report_invoice.xml#L4-L6 After the refactor, `o` no longer carries the customer language context at the point where `l10n_gcc_settings` is evaluated `_l10n_gcc_get_invoice_title()` was therefore called with the connected user's language instead of the customer's ### Steps to reproduce: - Install `l10n_sa` or `l10n_ae` and switch to the corresponding company - Create and confirm an Invoice (any data) - Set the customer language to Arabic - Print the Invoice Before the fix, the invoice title is displayed in English opw-6333472 Forward-Port-Of: odoo/odoo#272865
24 changes
Enhancements to existing features
The POS now sends buyer address details to Fiskaly only when they are actually available. This avoids transmitting placeholder values like "N/A" and helps ensure the information sent is more accurate and cleaner.
Original PR description
In this commit: ------------------- - Buyer address fields are optional and should only be sent to Fiskaly when they are actually available. - Avoid sending placeholder values like "N/A". If the data is not present, the fields should simply be omitted from the request. task: 6113133 Forward-Port-Of: odoo/enterprise#122188 Forward-Port-Of: odoo/enterprise#113621
This update fills in missing translations for user-facing messages across Point of Sale features. It improves the experience for non-English users by making dialogs, errors, alerts, and warnings easier to understand during day-to-day POS use.
Original PR description
pos* = All POS module In this commit: -------------------------------- Add missing translations for user-visible strings across POS modules. - Translated dialogs, errors, alerts, and other UI-visible messages - Updated Python-side UserError, ValidationError, and warning messages Task-5406947 Related PR-https://github.com/odoo/enterprise/pull/102094 Forward-Port-Of: odoo/odoo#273039 Forward-Port-Of: odoo/odoo#239972
This update fills in missing translations across Point of Sale screens, dialogs, errors, and warnings. It helps users see clearer messages in their language, making the POS easier to use and reducing confusion during daily operations.
Original PR description
pos* = All POS module In this commit: -------------------------------- Add missing translations for user-visible strings across POS modules. - Translated dialogs, errors, alerts, and other UI-visible messages - Updated Python-side UserError, ValidationError, and warning messages Task-5406947 Related PR-https://github.com/odoo/odoo/pull/239972 Forward-Port-Of: odoo/enterprise#122251 Forward-Port-Of: odoo/enterprise#102094
This update makes Odoo’s logging easier to configure for different environments, including custom log formats and external logging tools. It also fixes a naming issue so custom log levels work correctly without breaking the standard log level mapping.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
Resolved issues and error corrections
This update fixes an issue in the Point of Sale payment process so orders are handled more reliably. It helps reduce payment-related errors and makes checkout smoother for staff and customers.
Original PR description
wip 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 change fixes an intermittent issue in the Viva.com POS checkout test where the mocked webhook response could arrive before the payment or refund request had finished. As a result, the test could hang; the update makes the test wait at the right moment so the confirmation is always received reliably.
Original PR description
The Viva.com POS tour was failing intermittentely due to the mocked webhook response not waiting for the payment/refund request to finish. This would cause the tour to hang as it missed the webhook confirmation. We fix the issue by changing the `waitingCard` status to only be set after the payment request returns, and wait for this status before sending the fake webhook response. runbot-243758 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents a crash when a device session does not include the expected trust information. It makes the login/session flow more resilient for affected devices and avoids disruptions for users.
Original PR description
Some devices may not have a `trusted` key in their entry. This is the case for sessions created between these two commits: - https://github.com/odoo/odoo/commit/b6c2aafae2112ef98edca8a7f027716d9c15be11 - https://github.com/odoo/odoo/commit/61f22175ef3df37087887e7419dac54a620bbd55 Task-6348650
We fixed an issue that could crash an invoice when a payment term was selected and the currency was then removed. The system now safely uses a fallback currency for calculations, so users won’t run into this error while editing invoices.
Original PR description
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new…
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new invoice - Add a line - Add a customer - Save - Select payment term as `30% Now, Balance 60 Days` - Remove the currency. Error: ``` ValueError: Expected singleton: res.currency() ``` Cause: - This error only occurs when the selected payment term contains at least two due term lines [1]. - When the selected payment term has atleast two lines the check [1] assigns `on_balance_line` as false and the `else` block is evaluated where currency being an empty recordset (as the user removed it) causes the error from [line] when trying to perform `round()` on an empty res.currency recordset. Solution: - As the currency is a required field, user will not be able to save the record until a currency is assigned. - Used journal's currency or company's currency as a fallback when computing payment terms if the current currency is empty. [1]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L229 [line]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L240 sentry-7569922293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272073
This update fixes certificate import so the complete PEM certificate chain is loaded, not just the first certificate. It improves compatibility and reliability for workflows that depend on the full chain being present.
Original PR description
Previously, only the leaf certificate was parsed when loading PEM-encoded data, ignoring any additional certificates in the chain. This change updates the loading logic to include the full certificate chain, ensuring proper integrity and compatibility with flows that require it. Useful for this PR: odoo/odoo#254906 Task [link](https://www.odoo.com/odoo/project.task/6053921) task-6053921 Forward-Port-Of: odoo/odoo#255100
This update prevents a display error that could appear when a newly created receipt is deleted. It makes the status bar on stock pickings handle cases where nothing is selected yet, avoiding a traceback for users.
Original PR description
# How to reproduce - Create a new Receipt - Save - Delete the new Receipt # The issue A traceback is shown : `TypeError: Cannot read properties of undefined (reading 'label')` # Cause This is caused…
# How to reproduce - Create a new Receipt - Save - Delete the new Receipt # The issue A traceback is shown : `TypeError: Cannot read properties of undefined (reading 'label')` # Cause This is caused by the custom status bar for pickings `StockPickingLockedStatusBarField`. In its template, we replace the display of the current label : https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.xml#L20-L23 https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.xml#L4-L9 The issue is that the base implementation of the current label properly handles the case were no item is currently selected: https://github.com/odoo/odoo/blob/7630f8fe2d5198b7a1ed538241795dc26a497fa0/addons/web/static/src/views/fields/statusbar/statusbar_field.js#L298-L300 But the picking implementation does not : https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.js#L12-L14 And it seems that the template is quickly rendered without any selected item before deletion. opw-6345192 Forward-Port-Of: odoo/odoo#273030
This change removes an inefficient repeated lookup while determining a partner’s main user. As a result, large operations such as auto-subscribing many users now run much faster and use system resources more efficiently.
Original PR description
**Current behavior before PR,** Computing `main_user_id` of a partner involved filtering active users within a loop. To avoid losing the prefetching, we manually forced all partner users to be kept…
**Current behavior before PR,** Computing `main_user_id` of a partner involved filtering active users within a loop. To avoid losing the prefetching, we manually forced all partner users to be kept in the prefetch during each iteration. This caused performance issues as the recordset grew large (e.g., during auto-subscription). **Desired behavior after PR is merged,** All partner users are prefetched and filtered once, removing the need for a repetitive manual prefetch. **Benchmark,** The following observations were recorded when auto-subscribing users to a discuss channel at different scales. The _Before_ and _After_ results represent the max values from three consecutive tests. | Records | Before | After | | :--------| -------: | ---------: | | 3k | ~2.3s | <90ms | | 5k | ~3.8s | <160ms | | 10k | ~7.6s | <300ms | part of task-6116079 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271549
We fixed an issue in Kenyan PoS where selling a combo could be blocked by an eTIMS registration warning, even when only the individual items inside the combo need to be registered. With this change, combo parent lines are ignored for eTIMS checks, so orders can be completed normally.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#122179 Forward-Port-Of: odoo/enterprise#119362
This fix stops the point of sale from crashing when Adyen sends the same payment update more than once. It makes the payment flow ignore already-processed payment lines, so duplicate notifications no longer interrupt checkout.
Original PR description
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers…
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers webhook notifications at-least-once, so the ADYEN_LATEST_RESPONSE event can fire several times for a single payment, running handleAdyenStatusResponse concurrently. After the await on get_latest_adyen_status, a previous (duplicate) notification may already have resolved the payment line, so getPendingPaymentLine no longer returns it and the subsequent line.uuid dereference crashes. opw-6237987 patched the same root cause on a single line by adding an optional chaining operator in isPaymentSuccessful, which only moved the crash to the next dereference. Fetch the pending line once at the start of handleAdyenStatusResponse and bail out when it is gone, so every dereference below is safe. The same guard is added to the remaining branches of _adyen_handle_response for consistency with the existing Reject branch. opw-6237987 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271181 Forward-Port-Of: odoo/odoo#269720
When users apply a device-style shape to an image, the image will now be cropped to match that shape instead of always being forced into a square crop first. This preserves more of the original picture and avoids unnecessary cropping, especially for tall images.
Original PR description
Scenario: - insert image with ~ 1:2 ratio (height bigger than width) - set shape "iPhone `#2`" to that image Result: the image should fit without much cropping the 0.46:1 aspect ratio of the shape, but it is cropped 1:1 before being applied to it. Cause: when the image has a set aspect ratio, we are always cropping it to 1:1 aspect ratio in postProcessCroppedCanvas but it should be cropped to the shape aspect ratio as it was done in previous version. Fix: go back to what was done in saas-18.3 and apply the shape aspect ratio and not just square (1:1) aspect ratio. opw-5415137 Forward-Port-Of: odoo/odoo#250922
When a business card is scanned, the city information is now imported correctly along with the other contact details. This reduces manual cleanup and makes newly created contacts more complete right away.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
This fix ensures SEZ invoices in foreign currency are shown in the GSTR-1 export using the company currency (INR) instead of the invoice currency. It prevents incorrect values in the tax report spreadsheet and helps businesses file GST returns accurately.
Original PR description
Currently, when generatign GSTR-1 return spreadshee, SEZ invoices issued in a foreign currency are exported with their totals in the foreign currency rather than the company currency (INR) Steps to reproduce: - Create a B2B SEZ invoice in foreign currency - Go to Accounting > Reporting > [India] GST Return periods - Generate the GSTR-1 report for the period Issue: In the resulting spreadsheet, the "Invoice Value" column takes the invoice total in USD rather then INR opw-6292913 Forward-Port-Of: odoo/enterprise#121972 Forward-Port-Of: odoo/enterprise#121157
When multiple manufacturing orders are merged, any pending quality checks are now removed along with the canceled orders. This prevents outdated checks from staying visible and avoids confusion on orders that no longer exist.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous fix introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: odoo-dev@db93bd2 This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L2480 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- opw-6260735 Forward-Port-Of: odoo/enterprise#121717 Forward-Port-Of: odoo/enterprise#119525
This fix ensures customer invoices use the actual production cost of a serial/lot made for a sale, instead of falling back to the product’s standard price. It matters because invoicing now reflects the real cost of goods sold when items are produced specifically for an order, improving margin accuracy.
Original PR description
### Steps to reproduce: - Create a storable product P tracked by SN, fifo perpetual lot valuated using the MTO route and with a BOM: 1 x COMP - Create, confirm and validate an MO for 10 unit of P…
### Steps to reproduce: - Create a storable product P tracked by SN, fifo perpetual lot valuated using the MTO route and with a BOM: 1 x COMP - Create, confirm and validate an MO for 10 unit of P using COMP's at 10$ (by setting its standard price). - Create and confirm a Sales Order for 1 unit of P > This generate an MO - Validate this MO for a new serial say SN011 using a COMP at 20$. - Validate the Delivery Order using SN011 - Create and post the customer invoice #### > The invoice COGS uses Std Price rather than the 20$ lot's fifo value ### Cause of the issue: The cogs value are generated based on the moves returned by the `_get_stock_moves` call of the acount.move.line: https://github.com/odoo/odoo/blob/6a356cb0640ce20c71f20a8bd64ef99e76a82489/addons/stock_account/models/account_move_line.py#L66-L68 Currently, if an account.move.line is linked to a sale.order.line, this methods returns the entire pull of stock moves linked to the sol: https://github.com/odoo/odoo/blob/79c9e7de6764e7f8e47709b827df6eee81e72637/addons/sale_stock/models/account_move.py#L155-L156 However, these moves include both, the delivery move and the `move_finished_ids` of the MTO prodcution. This is problematic since the delivery move is considered as positive cogs qty and the MO is considered as incoming cogs qty leading to a sum of 0 cogs qty which in turns make the cogs price unit fall back to the product standard price instead of the fifo cost of the produced lot.: https://github.com/odoo/odoo/blob/6a356cb0640ce20c71f20a8bd64ef99e76a82489/addons/stock_account/models/stock_move.py#L257-L271 opw-6292048 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271018
This update fixes two manufacturing edge cases where expected component quantities were not handled correctly. It prevents validation errors when components are not reserved in advance and when serial-based manufacturing orders are split, so production flows continue smoothly.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Set your warehouse to manufacture in 2 steps (pick then manufacture). - Create a final product (FP) with a BOM in flexible…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Set your warehouse to manufacture in 2 steps (pick then manufacture). - Create a final product (FP) with a BOM in flexible consumption: - 1 x COMP (lot tracked) - Create and confirm an MO for 1 units of FP - Set the quantity producing on the MO to 1 > The consumed qty was updated to 1 unit - Set a lot on the pre-production pikcing and validate #### > The lot is not transfered to the MO which you are not able to validate since the registered component is lot less ### Cause of the issue: The issue is caused by https://github.com/odoo/odoo/commit/3223deb871ca4cb4ac0381e4321f2dbf79a60189 as the `qty_waiting` is based on the reservation state of the move origin of the move rather than its actual demand: https://github.com/odoo/odoo/blob/00118002bd6eab2f4c34a32e993a9219fded06ac/addons/mrp/models/mrp_production.py#L1419-L1426 In particular, since the backorder of the pre-production picking was not reserved (since nothing was available in stock), it was not taken into account as it should have been. Issue 2: Steps to reproduce: - In the settings Enable Multi-Steps Routes - Unarchive MTO - Create 3 products: - Final Product: Tracked by SN with a BOM: 1 X Super Component - Super Component: Tracked by SN, MTO with a BOM: 1 X Component - Basic Component: Put 10 units in stock - Create and confirm an MO for 3 units of Final Product > This should create an MO for 3 units of Super Component - Go to the Child MO > Cogs wheel > Split in 3 MO's - Click "Generate serial" on each Child MO and validate the first one - On the MO for Final Product > Cogs wheel > Split in 3 MO's - On the first MO, click "Generate Serial" > Error: Reserving a negative quantity is not allowed. ### Cause of the issue: The `action_generate_serial` calls in turn the `set_qty_producing`: https://github.com/odoo/odoo/blob/9fac1400fe5a8e665732c2ee3701c17c3495318f/addons/mrp/models/mrp_production.py#L1601 However, since the main MO was split the Super component demand is of 1 but each child MO provide an origin quantity of 1 so that the `new_qty` will be set to a negative one here: https://github.com/odoo/odoo/blob/9fac1400fe5a8e665732c2ee3701c17c3495318f/addons/mrp/models/mrp_production.py#L1418-L1426 But, since the first child MO was validated, there is already a move line associated to the Super component move and the `_set_quantity_done` will therefore try to adapt the reservation to a negative quantity which leads to the error: https://github.com/odoo/odoo/blob/9fac1400fe5a8e665732c2ee3701c17c3495318f/addons/stock/models/stock_move_line.py#L469-L470 opw-6128575 opw-6317083 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271123
This change replaces the previous memory profiling approach with a lighter-weight method that reduces the slowdowns caused during long-running requests. It also uses a simpler estimation method to better identify where memory growth is happening, helping teams troubleshoot performance issues more efficiently.
Original PR description
The previous memory profiler was causing a lot of performance issues. This is because tracemalloc tracks the allocations that happens at the python interpreter level by attaching to the cpython…
The previous memory profiler was causing a lot of performance issues. This is because tracemalloc tracks the allocations that happens at the python interpreter level by attaching to the cpython allocators. This first meant each allocation that happens through python has to go through a callstack while holding the GIL and preventing the thread and other threads from operating. This callstack does multiple things, first is walking the allocation back from the current frame up until the specified frame depth at the start of collection. The other is updating the internal object that keeps track of the allocations and what cause them up until now which degrades the performance even more when the allocator keeps running for a long time. Increasing the frame depth also means the partitioning becomes even more fragmented in the internal object and leads to higher memory usage. This in turns means lower performance as well. The issue becomes more evident when the overhead of tracemalloc blocks any execution even turning it off because the gil cannot be released until the full allocation execution happens. Currently this would happen on long enough requests or a high enough depth. Two PRs were made to try to address this issue. 1- https://github.com/odoo/odoo/pull/251950 : This PR tries the solution of having a lower frame depth but matching the frames based on a window of frames so that we can reconstruct an approximation of the flamegraph, for example: matching window of 2 frames 1 - > 2 - > 3 - > 4 2 - > 3 - > 4 - > 5 would mean that we would match frames 2 and 3 in both stack traces and append the first frame to the second callstack which would look like 1 - > 2 - > 3 - > 4 - > 5 Neverthless this was deemed to have too big of an assumption in the building heuristic. 2- https://github.com/odoo/odoo/pull/253120: This PR was supposed to be introducing memray as a profiler. Memray is the best tool for this usecase. First because it attaches on the native system allocation calls, and uses a file to append to on allocations. This solves both of the issues that we had in the beginning but the issue with memray is that it's an external tool that was deemed unnecessary to add. The final solution is this PR: The PR assumes a heuristic that in worker mode, a single worker handles one thread which mean that the process memory can be fully attributed to the request. The heuristic is also based that on a high enough sampling rate, the delta can be fully attributed to the current frame. This is a close enough approximation to know where to look but not what is the actual memory usage by line. Forward-Port-Of: odoo/odoo#270442 Forward-Port-Of: odoo/odoo#253604
This fix ensures that when a Point of Sale order linked to a sales order is refunded, the related invoiced quantity on the sales order is updated correctly. It also aligns refunds made from the PoS and from the backend so they no longer create inconsistent billing totals.
Original PR description
When making a refund of a PoS order that was created from a sale order, the sale order qty_invoice was not updated correctly. Steps to reproduce: ------------------- * Create a sale order with any product and confirm it * Open a PoS and settle the order * At this point the qty_invoiced should be 1 on the sale order line * Refund the PoS order from the PoS > Observation: The qty_invoiced is still one. Why the fix: ------------ We now take refund lines into account when computing the qty_invoiced. Note: ------------ There was an inconsistency between a refund made from the PoS and a refund made from the backend. The former is not linking the sale order line to the refund line, while the latter does. This was causing issue when refunding from the backend as it would count the refund twice. To fix this we now remove the link to the sale order line when refunding from the backend. opw-4991405 Forward-Port-Of: odoo/odoo#270388 Forward-Port-Of: odoo/odoo#259653
This change stops the same sold item from being refunded more than once. It helps ensure refund totals stay accurate and prevents accidental over-refunding at the cash register.
Original PR description
Before this commit, if an order line was already refunded, it was possible to refund it again. opw-6340931 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents point-of-sale payments from being created twice when an order is synced more than once. It also avoids a sync error that could happen when previously removed payment lines were processed again, making order updates more reliable after payment changes.
Original PR description
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was…
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was not idempotent and led to two issues: - The change/return cash payment is generated server-side in `_process_payment_lines` and has no uuid, so `_update_lines` cannot deduplicate it. Each extra sync therefore created an additional return payment. It is now removed before being recomputed, which also keeps it correct when the payments are edited after payment (new return amount, or no change at all). - `_update_lines` replays the client commands as-is. On a second sync, a delete command (`[2, id]`) targets a payment that the first sync already removed, and `_create_pm_change_log` crashed with a MissingError while reading the deleted record. Update/delete/unlink commands referencing records that no longer exist are now skipped. Note that delete/unlink commands only carry 2 elements, so the check runs before the `len(line) < 3` guard. Steps to reproduce: - Pay an order, then re-sync it (or edit its payments and sync again). => the return payment was duplicated, or a MissingError was raised. opw-6327912 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The disconnect button for French e-invoicing was renamed to use the correct wording instead of referring to Peppol. This makes the interface clearer for users managing French electronic invoicing settings.
Original PR description
The name of the disconnect button for the France e-invoicing was incorrect as it referenced peppol and was fixed in this pr to be called Disconnect French electronic invoicing task-6266337 Forward-Port-Of: odoo/odoo#272654 Forward-Port-Of: odoo/odoo#268536
14 changes
Enhancements to existing features
The Expense dashboard now follows the same filter rules as the list view for expenses in To Submit, Waiting Approval, and Waiting Reimbursement. This makes totals more accurate for managers, who can now see the amounts for the employees they oversee.
Original PR description
For the expense dashboard with the states 'To Submit', 'Waiting Approval' and 'Waiting Reimbursement', make these states compliants with the current filters of the list view. It means, for example, that a manager can see the total amounts of the people he manages. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270234
This update gives Odoo more flexible logging options, making it easier to tailor how logs are captured and stored. It also fixes an issue where custom log levels could be interpreted incorrectly, improving reliability for teams that rely on detailed logs for troubleshooting and monitoring.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
The point of sale product list now uses the larger layout on medium-sized tablets instead of switching to the compact view too early. This makes better use of screen space and improves browsing during checkout, including a fix for iPhone and iPad screen rotation so the layout updates correctly.
Original PR description
Previously, the product list was rendered in "small display" mode for all screen sizes below the medium breakpoint (< 992px). However, some small tablets are able to fully display the product list at the medium breakpoint (≥ 768px and ≤ 991px). After this fix, "small display" mode is only applied when the screen width is below 768px. This commit also includes a fix for iOS devices where the screen breakpoint was not correctly recomputed on orientation change. Task.6251934 Enterprise: https://github.com/odoo/enterprise/pull/119534 Forward-Port-Of: odoo/odoo#266704
The point of sale product list now uses the compact layout only on very small screens. On medium-sized tablets, more products will be shown at once, making browsing easier and improving the checkout experience.
Original PR description
Previously, the product list was rendered in "small display" mode for all screen sizes below the medium breakpoint (< 992px). However, some small tablets are able to fully display the product list at the medium breakpoint (≥ 768px and ≤ 991px). After this fix, "small display" mode is only applied when the screen width is below 768px. Task.6251934 Community: https://github.com/odoo/odoo/pull/266704 Forward-Port-Of: odoo/enterprise#119534
Resolved issues and error corrections
When a business card is scanned, the city field is now imported correctly along with the other contact details. This reduces manual cleanup and helps keep newly created contact records more complete and accurate.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
This change fixes how refunded point-of-sale orders affect the related sales order. Previously, a refund could leave the invoiced quantity incorrect, which could lead to misleading sales and billing figures; the update now counts refunds properly and avoids double counting in backend refunds.
Original PR description
When making a refund of a PoS order that was created from a sale order, the sale order qty_invoice was not updated correctly. Steps to reproduce: ------------------- * Create a sale order with any product and confirm it * Open a PoS and settle the order * At this point the qty_invoiced should be 1 on the sale order line * Refund the PoS order from the PoS > Observation: The qty_invoiced is still one. Why the fix: ------------ We now take refund lines into account when computing the qty_invoiced. Note: ------------ There was an inconsistency between a refund made from the PoS and a refund made from the backend. The former is not linking the sale order line to the refund line, while the latter does. This was causing issue when refunding from the backend as it would count the refund twice. To fix this we now remove the link to the sale order line when refunding from the backend. opw-4991405 Forward-Port-Of: odoo/odoo#270388 Forward-Port-Of: odoo/odoo#259653
This change prevents invoice email notifications from crashing after a quick edit when they are rendered in another language. It ensures the invoice totals can be processed safely, so notifications are sent correctly and users do not encounter errors.
Original PR description
**Steps to Reproduce:** - Install the Accounting and Contacts modules. - Enable Quick Encoding for Customer Invoices and Vendor Bills in the company settings. - Create a new customer: Assign a…
**Steps to Reproduce:**
- Install the Accounting and Contacts modules.
- Enable Quick Encoding for Customer Invoices and Vendor Bills in the company
settings.
- Create a new customer: Assign a salesperson.
- Ensure:
- The salesperson is not a login user.
- The customer language, salesperson's language, and Login user's language
are different. Example:
- Customer language: English
- Salesperson language: French
- Login user language: French
- Create a customer invoice using the Upload Document functionality.
- Select the customer created above.
- Use Quick Edit mode and enter an amount and Click Confirm.
**Issue:**
- When the invoice notification is rendered in a language different from the one
used during the write operation, the notification rendering flow calls
_notify_by_email_prepare_rendering_context().
- During rendering, the code executes:
```
self.tax_totals.get('total_amount_currency', 0)
```
- Since tax_totals is protected, the ORM returns False instead of the expected
dictionary, leading to:
```
AttributeError: 'bool' object has no attribute 'get'
```
**Root Cause:**
- This issue occurs in Quick Edit mode because tax_totals is [not read-only](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/views/account_move_views.xml#L1359)
in Quick Edit mode and is included in [the values](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/web/static/src/model/relational_model/record.js#L708) sent by the web client during write().
- During create()/write(), _get_protected_vals() marks tax_totals as protected.
- Since tax_totals is a [@api.depends_context('lang')](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L975) computed field, it
maintains a separate cache per language. [During write()](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L3955), the [field becomes
protected](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L3863) by [env.protecting()](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/odoo/orm/fields.py#L1738). While the protection is still active, the mail
notification flow renders the email using the recipient's language. If the
corresponding language-specific cache entry for tax_totals is not available,
the ORM cannot recompute the protected field and returns False instead
of the expected dictionary.
- The rendering code assumes tax_totals is always a dictionary and directly
calls .get(), leading to the crash.
**Solution:**
- Exclude tax_totals from _get_protected_vals().
- tax_totals is already handled explicitly after create()/write(), so protecting
it is unnecessary. This allows the field to be recomputed during notification
rendering when required.
**Result:**
- Invoice notifications render correctly in all languages.
- No RPC crash occurs when rendering notifications after Quick Edit.
**Runbot reproduction: [video](https://github.com/user-attachments/assets/5f045efb-37de-40aa-b135-1368b1601d61)**
**opw-6209647**
Forward-Port-Of: odoo/odoo#266335This fix ensures service sales from EU companies to customers in Northern Ireland are treated as non-EU transactions, instead of being reported with intra-community taxes. It helps prevent incorrect tax reporting in the EC Sales List when an invalid record is present.
Original PR description
…stomers The services sales done from a European company to a Northern Ireland (XI) company should not contain intra-community taxes but should be treated as third country (non-EU) transactions. We solve it by adding a check in the EC Sales List return that is only visible when a wrong record occurs. task-6007931
The GSTR-1 export now reports the invoice value for SEZ invoices in the company currency, INR, instead of keeping the foreign currency amount. This ensures the spreadsheet matches the required local reporting format and avoids incorrect values in tax submissions.
Original PR description
Currently, when generatign GSTR-1 return spreadshee, SEZ invoices issued in a foreign currency are exported with their totals in the foreign currency rather than the company currency (INR) Steps to reproduce: - Create a B2B SEZ invoice in foreign currency - Go to Accounting > Reporting > [India] GST Return periods - Generate the GSTR-1 report for the period Issue: In the resulting spreadsheet, the "Invoice Value" column takes the invoice total in USD rather then INR opw-6292913 Forward-Port-Of: odoo/enterprise#121972 Forward-Port-Of: odoo/enterprise#121157
All-day events imported from Google Calendar were being stored at midnight, which caused some users to see them on the previous day in list view. The sync now uses the same date handling as Odoo’s own calendar events, so all-day events display on the correct day everywhere.
Original PR description
When Google sends an all-day event, the payload only contains a date (no time), so the inbound sync stores start and stop at 00:00 UTC. The list view renders those Datetime fields in the viewing…
When Google sends an all-day event, the payload only contains a date (no time), so the inbound sync stores start and stop at 00:00 UTC. The list view renders those Datetime fields in the viewing user's timezone, so any user west of UTC sees the previous day. The calendar view stays correct because it reads the date part directly. The rest of Odoo stores all-day events at 08:00 and 18:00 UTC, which keeps the stored datetime inside the same calendar day: https://github.com/odoo/odoo/blob/327ad9b737b0f1d4c547c71a52c45d8433f2b3f4/addons/calendar/models/calendar_event.py#L408-L414 Apply the same 08:00 / 18:00 normalization when building values from a Google all-day payload, so events created on Google match events created in Odoo. Steps to reproduce: 1. Set your user timezone to America/Winnipeg. 2. Connect a Google account and run the calendar sync. 3. In Google Calendar, create an all-day event on January 31. 4. Sync, then open Calendar in list view in Odoo. => Start Date and End Date columns show January 30. Ticket [link](https://www.odoo.com/odoo/project.task/6145880) opw-6145880 Forward-Port-Of: odoo/odoo#262282
This update prevents an error that could occur when generating the GSTR-1 Excel report for a single company after working across multiple companies. It ensures the report downloads correctly instead of failing, improving reliability for Indian tax reporting.
Original PR description
Steps to reproduce: - Install `l10n_in_reports` module(Indian Localisation) - Create a branch in `IN Company` > Select both - Create separate invoices for each company - Created the GSTR-1 report for…
Steps to reproduce:
- Install `l10n_in_reports` module(Indian Localisation)
- Create a branch in `IN Company` > Select both
- Create separate invoices for each company
- Created the GSTR-1 report for both company
- While generating Excel, select only main company
Traceback:
```py
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 2537, in action_generate_gstr1_xlsx
gstr1_json = self._get_l10n_in_gstr1_json()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 1071, in _get_l10n_in_gstr1_json
'b2cs': _get_b2cs_json(AccountMoveLine.search(self._get_section_domain('b2cs'))),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 672, in _get_b2cs_json
for line, line_tax_details in tax_details.items():
^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'items'
```
Cause:
This issue occurs because, while generating the GSTR-1 Excel report for a particular month, [journal_items] contains account moves from both companies. This happens because the [domain] fetches records for both companies, resulting in move [lines] from both companies being included.
However, while generating the Excel report, only one company is selected. As a result, [tax_details_by_move] does not contain the move data for the branch company, which returns None, causing the error to be raised.
Solution:
Pass an empty `{}` for `tax_details` when only a single company is selected.
[journal_items]: https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L877
[domain]: https://github.com/odoo/enterprise/blob/770ffaac14bfcd2c54a7ce6aca27e0010e7884d4/l10n_in_reports/models/account_return.py#L1387-L1393
[lines]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L1074
[tax_details_by_move]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L880
opw-6242824
Forward-Port-Of: odoo/enterprise#118614This change ensures invoices sent through the Guatemala EDI service keep special characters like ñ, á, and é intact. It prevents validation errors and malformed certified XML when invoices are sent to the tax authority service.
Original PR description
**Steps to reproduce:** * Install the **l10n_gt_edi** module. * Configure a Guatemalan company with valid Infile credentials in the settings. * Create a product or customer with special characters…
**Steps to reproduce:**
* Install the **l10n_gt_edi** module.
* Configure a Guatemalan company with valid Infile credentials in the settings.
* Create a product or customer with special characters (e.g. `ñ`, `á`, `é`) in their name.
* Create a customer invoice containing this product/customer.
* Confirm the invoice to trigger the EDI send to the SAT (Infile).
**Observed behavior:**
* Infile intermittently rejects the invoice due to validation errors, or accepts it but the resulting certified XML has truncated or malformed text exactly where the special characters were located.
**Cause:**
* Odoo uses the `requests.post()` library to send the XML payload to Infile. By default, `requests` encodes string payloads using `latin-1` unless told otherwise.
* Because the request was missing the explicit `Content-Type: application/xml` header and the XML string was not explicitly encoded to `utf-8` before sending, Infile parsed the payload using an incorrect encoding. This caused it to drop or misinterpret special characters, leading to validation failures or corrupted XML content.
**Fix:**
* Explicitly include the `'Content-Type': 'application/xml'` header in the request to Infile.
* Explicitly encode the `xml_data` payload to `utf-8` (`xml_data.encode('utf-8')`) before passing it to `requests.post()` to guarantee the correct encoding is sent over the wire.
opw-6315654
Forward-Port-Of: odoo/enterprise#121729This fixes an issue in Point of Sale where default global discounts with decimal values could be misread in languages that use a comma as the decimal separator. As a result, discounts such as 8,33% now display correctly and are applied at the intended rate instead of being treated as a full discount.
Original PR description
When using Dutch (or similar locales where the decimal separator is a comma), a configured global discount percentage with decimals is misapplied in POS. For example, a default discount of 8,33% is…
When using Dutch (or similar locales where the decimal separator is a comma), a configured global discount percentage with decimals is misapplied in POS. For example, a default discount of 8,33% is shown in the discount popup as 8.33% and, when confirmed without editing, applies a 100% discount on the order instead of 8,33%. Steps to reproduce: ------------------- * Activate Belgian localization for accounting * Set the user language to Dutch (Netherlands) or Dutch (Belgium) * In Point of Sale settings, enable global discounts and set the default discount percentage to 8,33% * Open a POS session, add a product to the cart, and click Discount * Confirm the popup without changing the value > Observation: The popup displays 8.33% (with a dot). After confirmation, the order receives a full discount instead of 8,33%. Why the fix: ------------ The discount popup initialized its value with `String(discount_pc)`, which always uses a dot as decimal separator. POS then parses the input with locale-aware rules where `.` is the thousands separator, so "8.33" is read as 833 and capped to 100%. Format the default discount percentage with `formatFloat` so the popup starts with the correct localized value (e.g. "8,33"). opw-6334367
This fix prevents an error when users add an event talk reminder to their calendar from an email. It ensures the calendar file is generated in a format that calendar apps can read, so the invitation opens correctly instead of causing an internal server error.
Original PR description
Steps to reproduce =================== 1. Open the Events page on the website. 2. Open the OpenWood Collection Online Reveal event. 3. Go to Talks. 4. Favorite a talk to receive the talk reminder email. 5. Try to add the event to an iCal/Outlook calendar from the email. => Internal Server Error With commit [1], while switching from pytz to zoneinfo, we mistakenly set the `created` value in the ICS file to `datetime.timezone.utc`, which is not supported by `vobject`. This commit now uses ZoneInfo instead. [1] https://github.com/odoo/odoo/commit/6fdb36716aac5d2b084fb0faa94ccb2f3ee7f99c Task-6288817
1 change
Resolved issues and error corrections
When users scan a business card, the city name is now imported along with the other contact details. This reduces manual cleanup and makes newly created contacts more complete and accurate.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
6 changes
Enhancements to existing features
This change makes Odoo’s logging system easier to customize, allowing businesses and developers to define logging behavior in a more standard and flexible way. It also fixes an issue where custom log levels could be misread, which helps keep log output and configuration consistent.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
This change ensures that the unique transaction ID provided by Italy’s SDI is saved not only for sent documents, but also for received vendor bills. It improves traceability and makes it easier to match and audit incoming electronic invoices.
Original PR description
A unique transaction id is provided by the SDI for every document. This transaction id was saved on document sending, but discarded for received one. backport of f2cc23b30dd4 opw-6111186 Forward-Port-Of: odoo/odoo#268508
Resolved issues and error corrections
This fix prevents invoice email notifications from crashing when an invoice is created in Quick Edit and later rendered in another language. It ensures the invoice totals can be safely recalculated during notification sending, so users can confirm invoices without encountering errors.
Original PR description
**Steps to Reproduce:** - Install the Accounting and Contacts modules. - Enable Quick Encoding for Customer Invoices and Vendor Bills in the company settings. - Create a new customer: Assign a…
**Steps to Reproduce:**
- Install the Accounting and Contacts modules.
- Enable Quick Encoding for Customer Invoices and Vendor Bills in the company
settings.
- Create a new customer: Assign a salesperson.
- Ensure:
- The salesperson is not a login user.
- The customer language, salesperson's language, and Login user's language
are different. Example:
- Customer language: English
- Salesperson language: French
- Login user language: French
- Create a customer invoice using the Upload Document functionality.
- Select the customer created above.
- Use Quick Edit mode and enter an amount and Click Confirm.
**Issue:**
- When the invoice notification is rendered in a language different from the one
used during the write operation, the notification rendering flow calls
_notify_by_email_prepare_rendering_context().
- During rendering, the code executes:
```
self.tax_totals.get('total_amount_currency', 0)
```
- Since tax_totals is protected, the ORM returns False instead of the expected
dictionary, leading to:
```
AttributeError: 'bool' object has no attribute 'get'
```
**Root Cause:**
- This issue occurs in Quick Edit mode because tax_totals is [not read-only](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/views/account_move_views.xml#L1359)
in Quick Edit mode and is included in [the values](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/web/static/src/model/relational_model/record.js#L708) sent by the web client during write().
- During create()/write(), _get_protected_vals() marks tax_totals as protected.
- Since tax_totals is a [@api.depends_context('lang')](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L975) computed field, it
maintains a separate cache per language. [During write()](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L3955), the [field becomes
protected](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/addons/account/models/account_move.py#L3863) by [env.protecting()](https://github.com/odoo/odoo/blob/1f7a62d38303a992f501b4ecdb1bee437f7279b8/odoo/orm/fields.py#L1738). While the protection is still active, the mail
notification flow renders the email using the recipient's language. If the
corresponding language-specific cache entry for tax_totals is not available,
the ORM cannot recompute the protected field and returns False instead
of the expected dictionary.
- The rendering code assumes tax_totals is always a dictionary and directly
calls .get(), leading to the crash.
**Solution:**
- Exclude tax_totals from _get_protected_vals().
- tax_totals is already handled explicitly after create()/write(), so protecting
it is unnecessary. This allows the field to be recomputed during notification
rendering when required.
**Result:**
- Invoice notifications render correctly in all languages.
- No RPC crash occurs when rendering notifications after Quick Edit.
**Runbot reproduction: [video](https://github.com/user-attachments/assets/5f045efb-37de-40aa-b135-1368b1601d61)**
**opw-6209647**
Forward-Port-Of: odoo/odoo#266335Survey participants will now move to the next page correctly after reviewing scored answers, instead of being sent back to the homepage. This fixes a broken step in multi-page surveys and prevents users from losing their progress.
Original PR description
**Step To reproduce :** 1. Create a survey with `Scoring` set to `Scoring with answers after each page` 2. Add at least 2 pages, each with 1+ scorable question 3. As a public user, open the survey…
**Step To reproduce :**
1. Create a survey with `Scoring` set to `Scoring with answers after each page`
2. Add at least 2 pages, each with 1+ scorable question
3. As a public user, open the survey and start answering
4. Fill in the first page and click Continue
5. Correct answers are displayed with green/red highlights, submit button is replaced by Next
6. Click Next
7. Redirected to the homepage instead of the second page
**Issue:**
When survey scoring type is 'scoring_with_answers_after_page', after submitting a page the correct answers are displayed along with a "Next" button. Clicking "Next" redirects the user to the homepage because the answer_token is lost.
**Reason:**
The `<button id="next_page">` has no explicit `type` attribute, so it defaults to `type="submit"` per HTML spec. When clicked, the browser's default form submission fires a POST to `/survey/<survey_token>` (the answer_token is never in the URL path — only in the cookie). On the last page, `_nextScreen()` deletes the survey cookie to clean up after completion. The concurrent form POST then arrives at the server with answer_token=None → `token_required` → `redirect("/")`.
Additionally, jQuery's event delegation matches `button[type="submit"]` against the `type` property (which is `"submit"` by default for bare `<button>` elements), triggering `_onSubmit` which makes a second stale RPC call, compounding the issue.
**Solution:**
Added `event.preventDefault()` in the Next button's click handler within `_showCorrectAnswers` to stop the browser's default form submission behavior at the event level. This prevents the unintended POST request regardless of the button's type attribute, ensuring only the JS-driven `_nextScreen` transition executes.
opw-6268296
Forward-Port-Of: odoo/odoo#269476This change prevents an error that could occur when opening Talent Pools from an application if duplicate talent records existed. It helps recruiters access talent pools reliably and avoids a disruptive traceback in day-to-day use.
Original PR description
When multiple talent records share the same information, opening the Talent Pools smart button from a matching application will trigger a traceback. Steps to reproduce the error: - Install…
When multiple talent records share the same information, opening the Talent Pools smart button from a matching application will trigger a traceback. Steps to reproduce the error: - Install ``hr_recruitment`` module with demo data - Go to Recruitment > Applications > Talent Pools > Create a new pool - Go to Recruitment > Applications > All Applications > Create a new application with valid email > Click Add to Pool > Select the Talent Pool > Add to Pool - Duplicate the created talent record - Create another application with the same email > save > click Talent Pools Traceback: ```py ValueError: Expected singleton: hr.applicant(2, 1) ``` https://github.com/odoo/odoo/blob/d4e76a5663223a2a2c6e50d1701fabbdcaf32405/addons/hr_recruitment/models/hr_applicant.py#L857-L859 Here, the talent is searched using matching applicant information. When a matching talent has been duplicated, the search returns multiple records. Assigning a multi-records to the many2one field ``pool_applicant_id`` then raises a singleton error. Solution: Restrict the duplication of talent. sentry-7556261128 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270827
The expense counter on Sales Orders now includes all expenses linked to the order, not only those that created a sales order line. This makes the smart button number match the list of expenses users see when they open it, avoiding confusion.
Original PR description
**Before this commit** Only expenses that generated a sale order line on an SO would be counted in that SO's count of expenses, introducing confusing behavior with the smart button on the SO form view that would take the user to a list of all expenses that have anything to do with the current SO. **After this commit** We return to the behavior that was present in Odoo 18.1 where all expenses that are associated with a SO show up in that SO's "expense_count", making the number in the smart button consistent with the number of expenses that will be fetched when clicking on it. opw-6309575 Forward-Port-Of: odoo/odoo#272287
10 changes
Resolved issues and error corrections
This fix removes an access error that blocked standard POS users from opening the Kitchen Display app directly from the main dashboard. It now lets them reach the same screen they could already access from inside POS, making the experience consistent and preventing unnecessary interruptions.
Original PR description
**Description of the issue/feature this PR addresses:** When a POS user attempts to open the Kitchen Display app from the main dashboard, they are blocked by an Access Error, despite being able to…
**Description of the issue/feature this PR addresses:**
When a POS user attempts to open the Kitchen Display app from the main dashboard, they are blocked by an Access Error, despite being able to access the interface from within the POS app's sub-menu.
This occurs because the dashboard menu triggers a server action (`action_pos_preparation_display_kitchen_display`) to route the user. When a server action has no explicitly defined `group_ids`, Odoo's `_can_execute_action_on_records` method falls back to requiring `write` access on the underlying model (`pos.prep.display`) to execute the code. Since standard POS users do not have 'write' access to this model, the execution engine blocks the routing attempt.
This commit resolves the issue by explicitly appending the POS User group to the server action's `group_ids`.
opw-6305014
**Steps to reproduce:**
- As Mitchell Admin:
- Settings > Users & Companies > Users > Marc Demo > Access Rights > Sales > set POS to User
- As Marc Demo:
- Attempt to access Kitchen Display app > observe Access Error
- POS > Orders > Preparation Display > observe no error
**Current behavior before PR:**
- POS Users receive an Access Error when attempting to access the Kitchen Display app from the main dashboard
**Desired behavior after PR is merged:**
- No Access Error when POS Users access the Kitchen Display appWhen a business card is scanned, the city information is now imported correctly along with the other contact details. This makes newly created or updated contacts more complete and saves users from entering the city manually.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
When users choose documents to attach or link, the extra action buttons now stay hidden in that selection dialog. This makes the interface less cluttered and helps prevent confusion while picking documents.
Original PR description
When selecting documents for attachment/link, control panel actions were displayed upon selection. The document selection dialog uses the secondary documents view introduced in: https://github.com/odoo/enterprise/pull/89030/changes/f93c159c106d1dde70910ec590f8739e549b19cf Several document management actions were already hidden through the `documents_view_secondary` context, but `DocumentsAction` was still displayed upon selection. Hide `DocumentsAction` in the secondary view. Task-6236888
This fix ensures goods that fail quality checks remain available for vendor returns instead of being pulled back into the warehouse reception flow. As a result, teams can complete returns without the items getting stuck in another quality check process.
Original PR description
Steps to reproduce --- 1. Set a warehouse to three-step reception. 2. Add a quality control point on the Quality Control operation with a failure location. 3. Receive a storable product and fail the…
Steps to reproduce --- 1. Set a warehouse to three-step reception. 2. Add a quality control point on the Quality Control operation with a failure location. 3. Receive a storable product and fail the quality check, so the goods are moved to the failure location. 4. Return the failed goods to the vendor. Issue --- The vendor return never becomes available, because the returned goods are pulled back into the reception route instead of being free to ship back to the vendor. A failed check moves the goods to the failure location by changing the destination of the operation's move, so returning them brings the goods back through WH/Input. https://github.com/odoo/enterprise/blob/885edbc270a86ab76e0a6eff4acb5767c0fe29d1/quality_control/models/quality.py#L577-L589 A move applies the reception route's push rules once it is done, so landing back in WH/Input re-pushes the returned unit into Quality Control and re-creates a quality check on it, that push reserves the unit, and whether the new check is passed (pushed onward to stock) or failed (sent back to the failure location), it never stays available to continue to the vendor. https://github.com/odoo/odoo/blob/161715c850496d3683baa5d1600380470d0b5ff5/addons/stock/models/stock_move.py#L2285-L2287 opw-6243147
The Depreciation Schedule report now leaves the account code blank when that information is not available, instead of showing the word “False”. This makes the report clearer and avoids confusing output when multiple companies are selected.
Original PR description
The issue is occur, when multiple companies are selected and the Depreciation Schedule report is opened, report correctly displays the account code for the company selected as the root company.…
The issue is occur, when multiple companies are selected and the Depreciation Schedule report is opened, report correctly displays the account code for the company selected as the root company. However for the other selected companies, the account code is displayed as False To avoid displaying False in the report changed the behavior to pass a null value whenever the account code is not available. For more details, please refer to the attached video. Root Cause The issue occurs because the code field is set to `False` [here](https://github.com/odoo/odoo/blob/ff64328283ee3bcc361fa0604bd4b9da8e62e803/addons/account/models/account_account.py#L337) for companies that are not considered the root company. As a result the report directly displays False instead of leaving the field null Steps to Reproduce 1.create a demo database in 19.0 2. Create two assets, each belonging to a different company. 3. Open the Depreciation Schedule report. 4. Select the first company, then select the second company as well. 5. Notice that the account code is displayed correctly for the root company, while `False` is shown for the other company. OPW-6239737 UPG-4196503 with out fix <img width="1852" height="579" alt="image" src="https://github.com/user-attachments/assets/b99f343d-b624-4d95-b826-6afdd2ebaa4c" /> with fix <img width="1912" height="731" alt="image" src="https://github.com/user-attachments/assets/19112a08-1958-496d-868f-a4091a745842" /> see video https://github.com/user-attachments/assets/ec51bb47-6c64-4cee-b484-7a359ed36ee0
This update corrects the Peru Kardex PLE stock report so balances, costs, invoices, and return movements are calculated consistently in Odoo 19. It also improves support for related stock operations and landed costs, helping reduce reporting errors and manual corrections.
Original PR description
## Summary Forward-port of PR #88592 (Kardex PLE 12.1/13.1 report fixes) adapted to 19.0's `stock.move` architecture, where `stock.valuation.layer` was removed as an independent model. - **Running…
## Summary
Forward-port of PR #88592 (Kardex PLE 12.1/13.1 report fixes) adapted to 19.0's `stock.move` architecture, where `stock.valuation.layer` was removed as an independent model.
- **Running balances**: Replace per-move `remaining_qty`/`remaining_value` with accumulated `data_per_products` dict for correct cumulative totals
- **Fix broken `_append_historic_valuation_lines()`**: The existing 19.0 code called `self.env.cr.dictfetchall()` without prior SQL execution — replaced with proper `_read_group` tuple unpacking
- **Fix `_append_valuation_line()`**: Use `_read_group` on `stock.move` (is_in/is_out aggregation) instead of `qty_available` with `to_date` which doesn't provide correct cost data
- **Fix invoice association**: Use `.sorted('id')[:1]` to consistently pick the first-created invoice, matching 18.0's SQL `ORDER BY am.id NULLS LAST` behavior
- **Return operation types**: Add `stock_picking_return.py` to assign operation types 24/25/21 for return pickings
- **MRP support**: Detect `mrp_operation` picking type and assign operation types 19/27
- **Float formatting**: Add `float_repr` with 2-decimal precision for all numeric fields
- **19.0 API adaptations**: `is_storable` filter (replaces `type='product'`), `fields_list` parameter naming, security comment on `sudo()`
Related: #88592, #106679This change prevents a traceback when a negative forecast demand is entered in the last planning period. It ensures the remaining negative quantity is correctly carried into the first forecast, so planning continues to work as expected.
Original PR description
Steps to reproduce: - Fresh DB - Add a negative number to the forecast demand in the last period Cause: A variable was used without declaration Fix: According to odoo/enterprise#56128, it was intended that any remaining negative quantity to add should be added to the first forecast. Forward-Port-Of: odoo/enterprise#122261
This change restores the ability to book multiple appointments on the same resource when that is expected by the appointment setup. It prevents resources from being treated as unavailable too early, so scheduling works correctly for both capacity-managed appointment types and shareable resources.
Original PR description
There are 2 modes to manage multiple appointments per resource: - either the resource manages its limits - or the appointment type does Commit https://github.com/odoo/enterprise/commit/4c05037…
There are 2 modes to manage multiple appointments per resource: - either the resource manages its limits - or the appointment type does Commit https://github.com/odoo/enterprise/commit/4c05037 introduced batch computation to improve the performance of availability computations, but inadvertently prevented that second use-case from working. The problem was in the logic to decide which resources are allowed to have overlapping bookings. After https://github.com/odoo/enterprise/commit/4c05037 (but before this revision), only appointment types where manage_capacity = True and resource.shareable = True were allowed to overlap. After this commit, appointment types where manage_capacity = False (regardless of shareability of the resource) are allowed (up to the max_bookings capacity set on the type) as well as types where manage_capacity = True and the resource is shareable (as they were before https://github.com/odoo/enterprise/commit/4c05037). Tests are introduced to prevent future regressions. Task-4144524 Task-6344700
The Journal Audit report now generates PDFs without an extra blank page at the end when certain summary content is missing. This makes the printed report cleaner and avoids confusion for users reviewing or sharing it.
Original PR description
Steps to reproduce: 1. Set the active company as My Company (san francisco) 2. Navigate to Accounting > Review > Journal Audit 3. Remove all journals from the report except Bank and Misc. 4. Use the PDF action button to print the report. 5. The last page of the report is completely empty. https://drive.google.com/file/d/1otpniJgt1UNCe2hrUBwqIK58dGuXpu8T/view?usp=sharing This commit ensures that the Journal Audit report does not have blank pages when the global tax summary section is not present. It uses some features of QWeb outlined in the following docs article: https://www.odoo.com/documentation/19.0/developer/reference/frontend/qweb.html#loops opw-6224670
This change prevents an error that could occur when generating the GSTR-1 Excel report for one company while report data from multiple companies exists. It ensures the export completes successfully instead of failing, improving reliability for businesses using Indian localization.
Original PR description
Steps to reproduce: - Install `l10n_in_reports` module(Indian Localisation) - Create a branch in `IN Company` > Select both - Create separate invoices for each company - Created the GSTR-1 report for…
Steps to reproduce:
- Install `l10n_in_reports` module(Indian Localisation)
- Create a branch in `IN Company` > Select both
- Create separate invoices for each company
- Created the GSTR-1 report for both company
- While generating Excel, select only main company
Traceback:
```py
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 2537, in action_generate_gstr1_xlsx
gstr1_json = self._get_l10n_in_gstr1_json()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 1071, in _get_l10n_in_gstr1_json
'b2cs': _get_b2cs_json(AccountMoveLine.search(self._get_section_domain('b2cs'))),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 672, in _get_b2cs_json
for line, line_tax_details in tax_details.items():
^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'items'
```
Cause:
This issue occurs because, while generating the GSTR-1 Excel report for a particular month, [journal_items] contains account moves from both companies. This happens because the [domain] fetches records for both companies, resulting in move [lines] from both companies being included.
However, while generating the Excel report, only one company is selected. As a result, [tax_details_by_move] does not contain the move data for the branch company, which returns None, causing the error to be raised.
Solution:
Pass an empty `{}` for `tax_details` when only a single company is selected.
[journal_items]: https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L877
[domain]: https://github.com/odoo/enterprise/blob/770ffaac14bfcd2c54a7ce6aca27e0010e7884d4/l10n_in_reports/models/account_return.py#L1387-L1393
[lines]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L1074
[tax_details_by_move]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L880
opw-624282411 changes
Enhancements to existing features
Event template questions can now be reordered by dragging and dropping them in the Questions page. This brings the template experience in line with regular events and makes it easier to organize questions in the desired order.
Original PR description
In the even template, on the questions page, we can't drag and change the order of the questions. To fix it, we'll add the sequence field with handle widget to event.type questions list view to enable drag-and-drop reordering matching the behavir in event.event. Steps to reproduce: 1.Go to event templates 2.Select any templates 3.Go to questions page 4.We can't drag and drop questions opw-6260478
This update makes Odoo’s logging easier to customize, including support for declarative configuration and structured JSON logs. It helps teams route, format, and store logs in ways that better fit their operations and troubleshooting needs, while keeping existing logging behavior working as before.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
Resolved issues and error corrections
This update fixes an issue where pages could stretch wider than the screen and create unwanted horizontal scrolling. It improves how content fits on smaller or flexible layouts, making the interface more stable and easier to use without changing features.
Original PR description
Description of the issue/feature this PR addresses: **This PR addresses the horizontal scroll and layout responsiveness issues reported in [GitHub issue #222577](https://github.com/odoo/odoo/issues/222577).** - -Added overflow-x: hidden; to html, body, and #wrapwrap to prevent unwanted horizontal scrolling across the app. - Added max-width: 100%; and box-sizing: border-box; to the children of #wrapwrap to prevent content overflow. - Set width: 100%; and min-width: 0; on the main content section to ensure proper scaling and prevent flexbox overflow issues. - These are minor CSS/SCSS changes aimed at improving frontend layout behavior without breaking any existing features. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The certificate import process now reads the full PEM certificate chain instead of only the first certificate. This improves compatibility and helps ensure certificates work correctly in setups that depend on the complete chain.
Original PR description
Previously, only the leaf certificate was parsed when loading PEM-encoded data, ignoring any additional certificates in the chain. This change updates the loading logic to include the full certificate chain, ensuring proper integrity and compatibility with flows that require it. Useful for this PR: odoo/odoo#254906 Task [link](https://www.odoo.com/odoo/project.task/6053921) task-6053921
This fix corrects how loyalty discount lines are treated when taxes are calculated in Point of Sale. It ensures the frontend and backend agree on the final tax amount, preventing invoices from showing a small remaining balance after checkout.
Original PR description
When computing taxes for the order, we group the base lines based on a grouping key. One of the components of this key is `is_refund`, and reward lines where considered as refund lines, which caused…
When computing taxes for the order, we group the base lines based on a grouping key. One of the components of this key is `is_refund`, and reward lines where considered as refund lines, which caused them to be grouped separately. This caused a discrepency between the tax amount computed in the frontend and the one computed in the backend. Steps to reproduce: ------------------- * Change the rounding method to globally * Create a 21% tax not included in price * Create a product with a price of 76.01 and the tax created above * Create a loyalty program with a 10% discount * Create a POS order with the product above and apply the loyalty program * Validate the order and generate the invoice > Observation: The invoice states that 0.01$ is still due Why the fix: ------------ In `round_tax_details_tax_amounts`, we try to detect any delta with the expeced tax amount. To do that we group the base lines based on a grouping key. The grouping key `is_refund` was incorrectly set to `true` for reward lines, which caused them to not be grouped. The delta was then not detected and tax amounts were not adjusted. We now make sure not to consider reward lines as refund. opw-6052112
This change adds an extra step to properly close a popover during automated testing. It prevents a rare cleanup error that could make test runs fail intermittently, improving overall reliability without changing user-facing behavior.
Original PR description
Add an extra step to close the popover and prevent the `Component is destroyed` error[1], which can happen during hoots cleanup, similar to the issue we see when some dialogs perform RPCs as they are being destroyed. [1]: https://runbot.odoo.com/runbot/build/115972540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents situations where a restaurant POS order could look paid on the screen even though the saved order totals did not match the payment. It now uses the actual saved order data to validate payments and correctly alerts the system when a mismatch happens, reducing broken orders and payment inconsistencies.
Original PR description
In POS Restaurant, order lines are synced incrementally as a series of create/update/delete commands rather than as a full snapshot. This could leave the backend with fewer lines than the frontend in two ways: 1. A network interruption during a draft sync silently dropped some create/update commands, or a line was deleted directly from the backend while the frontend still held it with a server ID. 2. Even when all commands arrived, `_process_order` overwrote the server-computed `amount_total` with the client-supplied value, so `action_pos_order_paid` was comparing the client's claimed total against the payment instead of the actual sum of persisted lines. Additionally, `_process_saved_order` was swallowing the `UserError` raised by `action_pos_order_paid` when totals did not match, so the mismatch was only logged and the frontend never knew the order was broken. opw-6263116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a sign request is completed, the person who sent it will now receive the expected Odoo inbox notification if they use "Handle in Odoo". This fixes a missed alert that could cause users to overlook completed documents and slows follow-up workflows.
Original PR description
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign*…
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign* (`sign`) 2. Sets the current user's notification preference to "Handle in Odoo" (`inbox`) 3. Create a sign request and send it to Marc Demo 4. As Marc Demo, sign the request 5. **The user who sent the sign request did not receive a notification to notify them that the request was signed.** ## Fix This is a partial backport of both https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda (saas-18.2) and a related fix https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 (19.0). Before the first commit, users would not receive inbox notification when sign requests would be completed. ## Note to reviewer The issue only occurs in 18.0, as it is fixed by https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda in 18.2, but we can backport the fix from https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 from 18.2 to 18.4 if desired. opw-6251702
This fixes an error that could happen in live chat when a chatbot tried to hand over to an operator but none were configured. Instead of showing a traceback and interrupting the conversation, the chat now handles this situation more gracefully.
Original PR description
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install…
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install ``im_livechat`` module with demo data - Go to Live Chat > Configuration > Chatbots > Create a new chatbot > Add script > Step Type: Question > Set answers > Save > Add script > Step Type: Forward to operator > Only If: Set one of the above answers > Save - Go to Live chat > Channel > Click the configure channel on YourWebsite.com > Remove the operators > Save - Go to the chatbot > test > select the configured answer Traceback: ```py StopIteration ``` https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/im_livechat/controllers/chatbot.py#L65-L70 When the chatbot script reaches a Forward to operator step while no operator is configured in the live chat channel, no chatbot message is created. As a result, the generator iterates over an empty iterator, and the ``next()`` call raises a ``StopIteration`` exception, causing a traceback during the conversation. sentry-7435424405 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents a database error in the French PDP process when no start date is available. It makes the update logic handle missing dates safely, improving reliability for companies using this local feature.
Original PR description
Fixes _force_update_l10n_fr_f10_moves(). It would create a SQL query that compares a date to a bool when _pdp_get_flow_10_start_date() returned None.
This change fixes a problem where users could be sent back to the homepage after clicking Next in scored surveys. It ensures the survey continues to the next page as expected, preventing a frustrating interruption for respondents.
Original PR description
**Step To reproduce :** 1. Create a survey with `Scoring` set to `Scoring with answers after each page` 2. Add at least 2 pages, each with 1+ scorable question 3. As a public user, open the survey…
**Step To reproduce :**
1. Create a survey with `Scoring` set to `Scoring with answers after each page`
2. Add at least 2 pages, each with 1+ scorable question
3. As a public user, open the survey and start answering
4. Fill in the first page and click Continue
5. Correct answers are displayed with green/red highlights, submit button is replaced by Next
6. Click Next
7. Redirected to the homepage instead of the second page
**Issue:**
When survey scoring type is 'scoring_with_answers_after_page', after submitting a page the correct answers are displayed along with a "Next" button. Clicking "Next" redirects the user to the homepage because the answer_token is lost.
**Reason:**
The `<button id="next_page">` has no explicit `type` attribute, so it defaults to `type="submit"` per HTML spec. When clicked, the browser's default form submission fires a POST to `/survey/<survey_token>` (the answer_token is never in the URL path — only in the cookie). On the last page, `_nextScreen()` deletes the survey cookie to clean up after completion. The concurrent form POST then arrives at the server with answer_token=None → `token_required` → `redirect("/")`.
Additionally, jQuery's event delegation matches `button[type="submit"]` against the `type` property (which is `"submit"` by default for bare `<button>` elements), triggering `_onSubmit` which makes a second stale RPC call, compounding the issue.
**Solution:**
Added `event.preventDefault()` in the Next button's click handler within `_showCorrectAnswers` to stop the browser's default form submission behavior at the event level. This prevents the unintended POST request regardless of the button's type attribute, ensuring only the JS-driven `_nextScreen` transition executes.
opw-6268296
Forward-Port-Of: odoo/odoo#2694762 changes
Resolved issues and error corrections
When an incoming email is meant to create a vendor bill but the XML attachment cannot be processed, the XML is now kept instead of being discarded. This helps users review the original document and retry or resolve the issue without losing important billing data.
Original PR description
Issue: When receiveing an email on a purchase journal, if the XML raise an issue, it is discarded. Steps to reproduce: - Configure an incoming mail server - Set up an email alias for the Vendor Bill journal - Receive a mail with an XML (e.g. PEPPOL XML) which raise an issue Current Behavior: - XML is discarded Cause: To avoid keeping pictures,... from mail, every attachment from a mail that doesn't fill an account.move is discarded. As the XML is faulty, it doesn't fill the move and is discarded. opw-6288972
This change ensures that databases which were neutralized before Peppol is installed will still use demo mode. It prevents these databases from accidentally connecting to the live Peppol network when users activate the feature later.
Original PR description
When Peppol is installed on a database that was already neutralized (ex: a staging database where the feature is enabled after the neutralization happened), the account_peppol.edi.mode parameter is not set: data/neutralize.sql only runs at neutralization time, not when the module is installed afterwards. The demo/ data that also sets this parameter is not loaded on databases without demo data (real production/staging databases). As a result, _get_peppol_edi_mode() falls back to 'prod' and the neutralized database registers and sends documents against the live Peppol network. Steps to reproduce: - Neutralize a database on which Peppol is not installed yet - Install the account_peppol module - Open the Peppol settings / registration wizard: the mode is Production instead of Demo Force the demo mode in the pre_init_hook when the database is neutralized, mirroring data/neutralize.sql opw-6307710