Thursday, September 10, 2026
15 changes · saas-19.2
Resolved issues and error corrections
Vertical notebook tabs are now visually separated when using dark mode. This makes pages easier to read and navigate by clearly distinguishing each tab.
Original PR description
## Behavior Before the Commit When a user opens a page with a vertical notebook in dark mode, the different tabs aren't separate from one another. task-[5933892](https://www.odoo.com/odoo/project/4105/tasks/5933892) Forward-Port-Of: odoo/enterprise#126013
Vertical notebook tabs now line up correctly, making the affected dialogs easier to read and use. Long tab titles wrap onto a new line instead of disrupting the layout.
Original PR description
When a user opened a page with a vertical notebook, the tabs were not aligned with each other. Vertical notebooks should now have properly aligned tabs. If a tab title is too long, it will wrap onto the next line instead of breaking the layout. task-[5933892](https://www.odoo.com/odoo/project/4105/tasks/5933892) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279098
Creating a new job position no longer shows the same confirmation message twice in the activity log. This keeps the recruitment chatter cleaner and avoids confusion for users reviewing job position history.
Original PR description
When creating a new job position, "Job Position created" was rendered twice in the chatter log. This occurred because the mail subtype definition specified a redundant `description` field with the exact same text as the subtype's name, causing the chatter logic to display both. Removing the explicit `description` field ensures the message is only displayed once upon job creation. Task: 6486002 Forward-Port-Of: odoo/odoo#285018
This update cleans up references to an old developer option that is no longer supported. It helps avoid confusion for administrators and developers by ensuring the system no longer suggests using a removed feature.
Original PR description
The feature was removed in odoo/odoo#115076 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#283352
This fixes a website editor issue where applying text animation across multiple text blocks could make centered headings and paragraphs shift out of alignment. Animated text now keeps the intended layout, helping users safely style website snippets without breaking their page design.
Original PR description
### Problem: Text animation used a single span around the full selection range. When a selection crossed block elements, this placed headings and paragraphs inside a span, producing invalid HTML and changing their layout. ### Steps to reproduce: 1. Drag & drop a snippet (like the "Cover" block) that contains page centered text 2. Select a range of text spanning multiple block elements within the added snippet 3. Add an animation to the selected text. <img width="800" height="200" alt="image" src="https://github.com/user-attachments/assets/45074927-4d60-4517-b65b-7ba6d667e060" /> ### Solution: This PR splits the selection by block and creates one inline animation wrapper per block instead. The builder applies animation options to the resulting elements as one group, without changing the document's block structure. task-5155887 Forward-Port-Of: odoo/odoo#283176
Spreadsheet cells now display correctly when opened in Hoot test debug mode. The fix disables cell animations during these tests, avoiding misleading or incorrect spreadsheet data while keeping normal product behavior unchanged.
Original PR description
If you try to open a spreadsheet in debug mode in the Hoot tests, you will often end up with cells with wrong displayed data. That's because cell animations don't work in hoot (it patches `requestAnimationFrame`), so we end up with cell animations stuck in the first frame of the animation. We can simply disable the cell animations in the Hoot tests, as animations are not relevant to the tests. Task: [4909027](https://www.odoo.com/odoo/2328/tasks/4909027) Forward-Port-Of: odoo/odoo#216620
This fix prevents non-product sales order lines used only for display or notes from being selected or copied during manufacturing order confirmation. It helps keep manufacturing and inventory records accurate by ensuring stock movements are linked only to valid sales lines.
Original PR description
Issue: ====== before this commit, user was able to select a display SOL and at MO confirmation the SOL was copied to the stock move, so we end up with a stock move linked to a display SOL, which is not correct. Solution: ========= - add a domain on the SOL field as first guard layer - add check on the SOL on MO confirmation to prevent copying a display SOL to the stock move opw-6473017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287309 Forward-Port-Of: odoo/odoo#286534
The Mexican POS self-invoicing test was updated to match the newer flow where public users can no longer edit customer details directly. This keeps automated checks accurate and helps ensure receipts and self-invoicing continue to work reliably under the updated customer data rules.
Original PR description
Before the related pr commit: - Public users could update customer data during the self-invoicing flow. - The test_qr_code_receipt_mx test relied on this behavior when updating customer data. After the ref commit: - Public users can no longer update customer data during self-invoicing. - Update test_qr_code_receipt_mx to create a new partner with the required customer data when the order is not linked to a customer. Related PR: odoo/odoo#283470 Task-6272660 Forward-Port-Of: odoo/enterprise#130700 Forward-Port-Of: odoo/enterprise#129948
The Indian e-invoicing check now opens a list only when missing e-invoices are actually found. When it does open, it is limited to the specific invoices that need attention, avoiding confusing unfiltered or overly broad results.
Original PR description
The `missing_einvoice` check passed custom `views` but no explicit `domain`, so its action ignored the `moves` recordset and instead opened all matching `account.move` records — an unfiltered list when no invoices were missing, and every eligible invoice (not just the flagged ones) otherwise.
Guard the action to only build when `moves` is non-empty, and pass `domain=[('id', 'in', moves.ids)]` so it's always scoped to the invoices actually found.
task-6544790
Forward-Port-Of: odoo/enterprise#130483Fixed a display issue in quotations where section totals could appear under the wrong column or be cut off after enabling the Related Intervention column. This keeps totals readable and correctly aligned for users preparing sales documents with field service planning details.
Original PR description
Steps to reproduce: --- - Install `planning_field_service_sale_timesheet` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related…
Steps to reproduce: --- - Install `planning_field_service_sale_timesheet` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related Intervention` column from the column selector. Issue: --- - When the Related Intervention optional column is enabled, the section line's aggregated Amount value appears in the wrong column or is clipped. Root cause: --- - `getSectionColumns()` computes the section title's colspan as `columns.length - sectionCols.length + 1` [1]. This formula assumes all non-section columns sit in the middle of the list, with the aggregated amount column (`price_subtotal`) anchored at the right end. - The `planning_slot_id` [2] was added via `position="inside"`, which appends it at the end of `<list>` after `price_subtotal` — breaking that assumption by placing a non-section column after the aggregated amount column. - This makes the section title colspan one unit too wide when `task_id` is enabled, shifting the section's aggregated Amount cell past the `price_subtotal` header column. Fix: --- - Changed the xpath to insert `planning_slot_id` after the `discount` field, placing it in the middle of the column list where the colspan formula correctly absorbs it into the title span and keeps the amount column aligned. [1]: https://github.com/odoo/odoo/blob/1ad38d396eb60858231ad667d9e71e8bee5b5ab2/addons/account/static/src/components/section_and_note_fields_backend/section_and_note_fields_backend.js#L453 [2]: https://github.com/odoo-dev/enterprise/blob/5b969ec8adba782f793ce3bae4ab175cc14d13d0/planning_field_service_sale_timesheet/views/sale_order_views.xml#L9-L11 Before: --- <img width="1248" height="210" alt="image" src="https://github.com/user-attachments/assets/5863331c-5fea-43cc-ab58-ae26546d97ee" /> After: --- <img width="1243" height="252" alt="image" src="https://github.com/user-attachments/assets/0c336f04-d3ab-4aad-b6d1-eb4e734118f7" /> opw-6472638 --- Forward-Port-Of: odoo/enterprise#129125
This fixes an issue where purchase stock reordering rule tests could fail in databases installed without demo data. It makes the test setup work reliably even when optional inventory tracking features are not pre-enabled, improving confidence in automated quality checks.
Original PR description
Steps to reproduce ------------------ 1. install purchase_stock in a database without demo data 2. run any test in TestReorderingRule 3. observe the error: can't write on invisible field 'tracking' Note: This fix is only relevant when you run the test on an empty database, the demo data enables the Lots & Serial Numbers.
Timesheet email suggestions from designated sender addresses are no longer automatically linked to projects or tasks. This prevents incorrect timesheet categorization for special addresses such as online@odoo.com and keeps suggested work items more accurate.
Original PR description
Before this commit, incoming email suggestions were automatically matched to tasks or projects whenever the sender’s email address could be linked to a partner in the database. In certain niche cases, this resulted in unwanted matches for specific email addresses or partners. After this commit, Email suggestions originating from designated addresses (e.g., online@odoo.com) are now excluded from task/project matching. task-[6414046](https://www.odoo.com/odoo/project/4105/tasks/6414046) Forward-Port-Of: odoo/enterprise#125645
Generating sample timesheet data now skips partners that do not have an email address, preventing an error in the Timesheet Assistant. This helps users complete sample data setup reliably even when customer records are incomplete.
Original PR description
Forward-Port-Of: odoo/enterprise#131002
This fix prevents a company's designated project documents folder from being archived by mistake. It helps keep project document organization intact and avoids disruption for users relying on the shared projects folder.
Original PR description
The company's project folder is supposed to be [impossible](https://github.com/odoo/enterprise/blob/20cc61e69aa3f6a59de1e962b25ce11fa402bf22/documents_project/models/documents_document.py#L44) to archive, by using the `_unlink_except_company_folders` logic. However, the method that adds the company field to the list of fields to check was missing, so it was still possible to archive a folder set as projects folder. Forward-Port-Of: odoo/enterprise#120605
Sold-out event tickets or time slots now correctly show that no seats can be ordered, instead of falling back to the default per-order limit. This prevents future event sales flows from accidentally allowing customers to request unavailable tickets.
Original PR description
### Steps to reproduce: event = env['event.event'].create({ 'name': 'Repro Event', 'date_begin': '2026-09-01 08:00:00', 'date_end': '2026-09-01 18:00:00', }) ticket =…
### Steps to reproduce:
event = env['event.event'].create({
'name': 'Repro Event',
'date_begin': '2026-09-01 08:00:00',
'date_end': '2026-09-01 18:00:00',
})
ticket = env['event.event.ticket'].create({
'event_id': event.id,
'name': 'VIP',
'seats_limited': True,
'seats_max': 1,
})
env['event.registration'].create({
'event_id': event.id,
'event_ticket_id': ticket.id,
'name': 'Attendee 1',
'state': 'open',
})
ticket.seats_available -> 0
ticket.is_sold_out -> True
result = ticket._get_current_limit_per_order(event=event) print(result) # {ticket.id: 30} -- expected {ticket.id: 0}
### Issue and Expected
`_get_current_limit_per_order()` used `if not seats_available:` to detect the "no limit" case returned by `_get_seats_availability()`. That check is truthy for both `None` (genuinely no limit) and the integer `0` (fully booked), so a sold-out ticket/slot combination was incorrectly treated as unlimited and returned `limit_max_per_order or EVENT_MAX_TICKETS` (e.g. 30) instead of `0`.
### Fix
`_get_seats_availability()` explicitly documents `None` as the "no limit" sentinel, with `0` meaning "constrained, zero seats left". Use `seats_available is None` to preserve that distinction instead of a falsy check.
No functional regression was found in the current website_event flow: sold-out slots/tickets are filtered or re-derived independently before reaching this value in every existing UI path. This fixes the underlying contract of the method itself, so future or additional callers don't inherit the wrong value.
https://github.com/odoo/odoo/issues/284098
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#284100