Monday, September 7, 2026
70 changes · master
Resolved issues and error corrections
The messaging menu now explicitly opens on the intended Chats tab instead of relying on fallback behavior. This prevents future tab-order changes from accidentally opening the wrong section and makes the user experience more predictable.
Original PR description
Before this commit, the systray state is inserted with `activeTab: MENU_TABS.CHATS`, a name no module defines, so the value is undefined and the state links no tab at all. This happens because each module names its own tabs, and the discuss one declares `MENU_TABS.CHAT`. The eager compute of `activeTab` hides the mistake: with no tab to keep, it falls back to the first visible tab, which is Chats whenever it is shown, as its sequence is the lowest. This commit inserts `MENU_TABS.CHAT`, so the state says which tab it opens on rather than depending on the sequences around it.
The Time Off Gantt view no longer displays an unnecessary “Undefined Employee” row when grouped by employee. This removes visual clutter and makes employee time off planning clearer for HR users.
Original PR description
Since web_gantt creates a placeholder group for optional fields, an "Undefined Employee" row was displayed when grouping by employee in the Time Off Gantt view. Add `required=True` to `employee_id` on `hr.leave.report.calendar` to prevent rendering this empty row. Task: 6537247
Certificate records can now be created or updated from the user interface without errors when uploading certificate files. This prevents a traceback caused by the newer upload format and keeps certificate management working smoothly for users.
Original PR description
Description of the issue this commit addresses: Since https://github.com/odoo/odoo/commit/23a7d8cc5b1d, binary values uploaded from the UI are dictionaries containing the filename and base64 content. Certificate creation parses the value before ORM normalization and calls bytes() on the dictionary, causing a traceback. --- Desired behavior after this commit is merged: This commit normalizes certificate content through the binary field converter before parsing it, allowing certificates to be created or updated from the UI. --- task-6538863 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Intrastat report lines now appear in a consistent order across different database environments. This prevents environment-specific test failures and reduces the risk of confusing report differences caused only by internal currency IDs.
Original PR description
`_intrastat_groupby_label_builder` calls `sorted(grouping_keys)` on JSON strings to determine the order of intrastat report lines. Those strings contain `"invoice_currency_id": <int>`, an…
`_intrastat_groupby_label_builder` calls `sorted(grouping_keys)` on JSON
strings to determine the order of intrastat report lines. Those strings
contain `"invoice_currency_id": <int>`, an environment-dependent integer.
When two groups share all other dimensions but differ only in currency,
the sort compares the serialised integers lexicographically, so the group
order depends on the specific integer values of each currency in the DB.
The values differ between environments because `odoo/modules/db.py` reads
the `ODOO_RUNBOT` / `ODOO_TEST` environment variables at import time
(`RANDOM_SERIAL`). When set, it runs `base/data/base_data_test.sql` after
the normal bootstrap, which executes
`select setval('res_currency_id_seq', 97)`, advancing the sequence by 96
before any currency is loaded from `res_currency_data.xml`. This shifts
every currency ID up by 96: SEK becomes 114, EUR becomes 222. As strings,
"114" < "222" (first character), so SEK sorts before EUR, breaking the
test. On a standard local install the sequence is not advanced: SEK=18,
EUR=126. As strings "18" > "126" (second character, '8' > '2'), so EUR
sorts first, matching what the test expected.
Steps to reproduce the failure (before this fix):
Local (EUR sorts first, test passes):
./odoo-bin -d test_local -i account_intrastat --stop-after-init
> SEK=18, EUR=126 → "18" > "126" as strings → EUR first
Runbot-like (SEK sorts first, test fails):
ODOO_RUNBOT=1 ./odoo-bin -d test_runbot -i account_intrastat --stop-after-init
> base_data_test.sql pre-advances res_currency_id_seq to 97
> SEK=114, EUR=222 → "114" < "222" as strings → SEK first
> Alternative: restore any master-all runbot DB dumpThe help message shown when no records exist is now tailored separately for tax returns and working files. This avoids confusing users by referring to tax returns when they are viewing working files.
Original PR description
Before this commit: - There is a common empty list help for tax returns & working files. This is confusing in the case of working files, as the help states Tax Return in it. After this commit: - There are now separate empty list helps for both actions. Task-6475771
The website shop header now uses the already saved cart quantity when available instead of reloading the full cart each time. This avoids unintended cart resets or recovery actions while customers are browsing or completing payment, improving checkout reliability.
Original PR description
`header_cart_link` computed the badge quantity with `request.session.get('website_sale_cart_quantity', request.cart.cart_quantity)`. Python evaluates the default argument unconditionally, so every render resolved `request.cart` even when the quantity was already cached in the session. Resolving the cart runs `_get_and_cache_current_cart`, which can mutate the session (cart reset, abandoned-cart recovery) as a side effect of merely rendering the header.
Read the cached quantity directly when the session key is present, falling back to `request.cart` only when it is absent.
This is needed for https://github.com/odoo/odoo/pull/268897 to prevent the cart from being reset while waiting for the user to do the payment.This fix validates key French Flow 10 e-invoicing report fields before sending them to the public platform. It helps prevent full report rejections by flagging affected journal entries when text, tax, company, or address values do not meet required limits.
Original PR description
Some Flow 10 values are generated without applying the length and format constraints expected by the PPF. Long free-text values, oversized VAT numbers, and invalid address data can therefore cause an entire report to be rejected. Limit product names and invoice notes to their allowed lengths and normalize country codes. Validate the declarant SIREN, VAT number lengths, and address values before sending so affected journal entries are marked as errors and excluded from the report. No Task id Forward-Port-Of: odoo/odoo#286887 Forward-Port-Of: odoo/odoo#286536
Internal users assigned to tasks in invitation-only projects can now open their assigned task links without being blocked by project-level access errors. The fix preserves project privacy, so users can access only the task they are assigned to without exposing other project tasks.
Original PR description
Issue: Internal users assigned to a task in an "Invited internal users" project can read the task but may receive an access error when opening it. Adding them as project followers avoids the error…
Issue: Internal users assigned to a task in an "Invited internal users" project can read the task but may receive an access error when opening it. Adding them as project followers avoids the error but also exposes the project's other tasks. Steps to reproduce: - Set a project's visibility to "Invited internal users". - Assign an internal Project user to one of its tasks. - Keep the user out of the project's followers. - Open the assigned task through its access link. Cause: The task form loads feature flags whose computations read their values from the parent project. These computations run as the assignee, who can read the assigned task but not the invited-only project, causing a project access error. Additionally, the project many2one widget declares `is_template` as a related field. This makes web_read request `project_id.is_template` even though the widget uses the task's own `is_template` value. https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/models/project_task.py#L277 https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/models/project_task.py#L295 https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/static/src/components/project_many2one_field/project_many2one_field.js#L36-L39 Solution: We need to compute the inherited task feature flags with elevated access so their values do not depend on the assignee's access to the parent project. declare `is_template` as a dependency of the current task instead of a related field of `project_id`. The task form therefore no longer reads the inaccessible project while its access restrictions remain intact. opw-6475880 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284196
The AI chat agent filter now loads and paginates results using the selected agent from the start, instead of filtering only what was already loaded. This prevents the chat list from getting stuck with too few conversations and keeps agent-specific chat views consistent when navigating back.
Original PR description
The AI chat tab has a dropdown allowing to filter it on a specific agent. The filter is applied client-side only, which is incompatible with lazy loading. A `load_more` batch fetched from the unscoped tab domain can come back mostly unrelated to the selected agent. Once filtered down it may render too little content to overflow the scrollable area. The bottom scroll trigger that requests the next batch then never fires again, leaving the tab stuck showing fewer matching channels than actually exist. The dropdown now sets its own filter through `mail`'s new `MessagingMenuUIState.pluginFilters`, which goes through the real fetch and pagination: the agent scope is resolved server-side and ANDed into the tab's domain community: https://github.com/odoo/odoo/pull/286451
This update fixes small visual inconsistencies in Odoo forms on mobile screens, including extra spacing, oversized tag delete buttons, and a misaligned CRM probability icon. The result is a cleaner and more consistent experience when viewing or editing records on smaller devices.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Add Font dialog now uses the standard switch control, so the “Serve font from Odoo server” option shows its checked state correctly and can be toggled with the keyboard. This improves usability and accessibility while removing obsolete duplicate styling.
Original PR description
[FIX] html_editor, website: generalize Switch component --- __Problem__ In the "Add font" dialog, the "Serve font from Odoo server" switch never shows its check mark, and cannot be toggled with…
[FIX] html_editor, website: generalize Switch component --- __Problem__ In the "Add font" dialog, the "Serve font from Odoo server" switch never shows its check mark, and cannot be toggled with Enter. __Reason__ The dialog reimplements the switch markup by hand instead of using the `Switch` component. Two things the component does were lost in the copy: - the knob glyph is a `::before` ligature, so it only renders if the span carries the `oi oi-filled` classes. The copy has a bare `<span/>` and stays blank once checked. - `Switch` supports toggling with `Enter`, which the copy does not handle at all. `Switch` itself was not directly usable here: it had no way to set an `id` (needed by the external `<label for=...>`). __Fix__ Make `extraClasses` optional, add an `id` prop, and use the component in the dialog. Toggling with `Enter` also failed to call `onChange` in `Switch`, leaving the owner state out of sync with the displayed value; this is fixed too. `labelIcon`/`labelIconClass` props are added for the `ai_website` counterpart of this fix. Finally, `website.editor.ui.scss` still carried a copy of the `.o_switch` rules, dead since the styles moved next to the component in `html_editor`. It is removed. + Enterprise PR: odoo/enterprise#130453 task-6377407
This fixes an issue that prevented users from adding extra images to products from the eCommerce tab. Product teams can now upload additional product media without encountering an error during the add process.
Original PR description
Steps to reproduce: 1. Open a product form view. 2. Go to the eCommerce tab. 3. Click on 'Add Media'. 4. Upload an image. 5. Click on 'Add'. Issue: - Adding an image fails with `ERR_INVALID_URL` because the generated data URL contains `[object Object]`. Cause: - The `raw` value returned by `searchRead` is a binary object containing `filename`, `content`, and `size`, but `convertToWebpFormat` passes the whole object as the image data to `generateImageVariants`. Fix: - Pass the `content` of the binary value to `generateImageVariants` instead of the whole `raw` object. opw-6542393
The member panel now positions the owner or admin crown icon next to the member's name instead of centering it across the full member entry. This makes the member list look cleaner and easier to read when extra status text appears below a name.
Original PR description
Before this commit, crown icon of a member in member panel was dead center to the member item as a whole. This means that if the member had name + another row of text (e.g. Back on X), then the crown would not be aligned with the member name. Before / After <img width="257" height="277" alt="Screenshot 2026-09-07 at 14 58 09" src="https://github.com/user-attachments/assets/289a5aa5-519e-4f0c-b226-5ed8b5b70ded" /> <img width="257" height="279" alt="Screenshot 2026-09-07 at 15 10 44" src="https://github.com/user-attachments/assets/4c29cf64-f759-476a-8663-efa8ab689d26" />
Fixed an issue where uninstalling certain modules could fail if they were linked to AI composer rules. Related model-specific AI rules are now removed automatically during uninstall, preventing conflicts and keeping module removal reliable.
Original PR description
## Issue When uninstalling a module that defines a model referenced by an `ai.composer` configuration, the corresponding `ir.model` is deleted. Deleting the `ir.model` sets the `focused_model_id` of…
## Issue
When uninstalling a module that defines a model referenced by an `ai.composer` configuration, the corresponding `ir.model` is deleted.
Deleting the `ir.model` sets the `focused_model_id` of the related `ai.composer` record to `NULL`.
The unique index on `ai.composer` uses `NULLS NOT DISTINCT`:
```python
_unique_agent_interface_model = models.UniqueIndex(
"(ai_agent_id, interface_key, focused_model_id) NULLS NOT DISTINCT",
)
```
As a result, `NULL` values are considered equal by the unique index.
If both a generic rule and a model-specific rule exist:
* `(agent, media_dialog, NULL)`
* `(agent, media_dialog, product.image)`
uninstalling the module that provides `product.image` deletes its `ir.model`, which sets `focused_model_id` to `NULL` on the model-specific rule.
This results in two identical `(agent, media_dialog, NULL)` entries and raises a `UniqueViolation`, preventing the module from being uninstalled.
## Fix
Set `focused_model_id` to `ondelete='cascade'`.
When the `ir.model` is deleted during module uninstallation, the corresponding model-specific `ai.composer` record is deleted instead of setting `focused_model_id` to `NULL`.
runbot-945683This fixes Spanish TicketBAI reporting for point-of-sale orders that use gift cards. Gift card refund amounts are now shown with the correct sign, preventing mismatches between line totals and the overall invoice total.
Original PR description
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and…
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and l10n_es_edi_tbai_pos with demo data - Create a gift card (add a tax to the discount product, any 0%) - start pos, add a product and use the gift card - fulfill the order - go to backend and open that order - In the TicketBAI XML, the values for the giftcard product will be positive, causing an inconsistency between the product line total and the invoice total [1] https://github.com/odoo/odoo/commit/0bbc5ebdcc7e014d87130b2ff9cee98e3aa7479a [2] https://github.com/odoo/odoo/commit/b17c9713e7a3305c240298fa54fcf1bc87a9bb8c FIX - we used to determine `sign` based on each order line's `is_refund` property - this property is quite sensitive as it depends on factors like line's qty, price, is reward or not. - so its better to depend on order's refund property for sign reversal https://github.com/odoo/odoo/blob/4fef2c5b69fac10594fac81b149d542ee4621b13/addons/point_of_sale/models/pos_order.py#L1768 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286448 Forward-Port-Of: odoo/odoo#278042
Dark mode color palettes now load correctly and include the full set of colors used by the interface. This prevents missing or incorrect colors in items such as kanban cards, tags, badges, and color lists, improving visual consistency for users working in dark mode.
Original PR description
1) The "$o-colors" css variable was rebuilt in "secondary_variables.dark.scss", which loads after community's "primary_variables.scss" already assigned it via !default. The dark "$o-colors: ()!default;" reset was silently skipped, so dark colors were appended onto the light ones instead of replacing them, doubling "$o-colors" to 24 entries. => Moving this logic to "primary_variables.dark.scss", which correctly loads first. 2) "$o-colors-secondary-original" only listed 18 colors instead of the 44 used in the original "$o-colors-secondary" of light mode, meaning the dark mode's total palette had far fewer entries than the light mode leading to missing coloring in kanban, tags, badges and colorlist. => Extending the list so that the dark mode "$o-colors-secondary-original" matches the original "$o-colors-secondary" light mode's 44 colors. related: https://github.com/odoo/odoo/commit/1dd67666ce06a9ee44a193e8006cf61aa71479c3
Rental products now show zero availability when no matching rental window exists, instead of triggering an error. This helps customers and staff complete searches or bookings without unexpected interruptions.
Original PR description
`_get_free_qty` computes the free quantity for a rental period by taking the minimum `quantity_available` across the availabilities returned by `_get_availabilities`. When that method returns an empty list (e.g. no availability windows overlap the requested period), `min()` raises a `ValueError` instead of returning a quantity. This commit passes `default=0` to `min()` so `_get_free_qty` returns 0 when there are no availabilities, instead of crashing. task-6026756 See also: - https://github.com/odoo/odoo/pull/254869
The AI website Add Page dialog now shows the Generate text switch correctly and lets users toggle it with the keyboard. This improves accessibility and makes the dialog behave consistently with the rest of the interface.
Original PR description
[FIX] ai_website: broken switch in the "Add page" dialog --- __Problem__ In the AI "Add page" dialog, the "Generate text" switch never shows its check mark, and cannot be toggled with Enter. <img width="439" height="326" alt="image" src="https://github.com/user-attachments/assets/0dc38547-679f-4fe1-9fda-a93213adc3d4" /> __Reason__ The dialog reimplements the switch markup by hand instead of using the `Switch` component: its `switch-slider` span misses the `oi oi-filled` classes the knob ligature needs to render, and nothing handles `Enter`. The hand-written markup is also why the icon is the hardcoded `/ai/static/description/icon.png` with inline sizing rather than the `o_ai_icon` font icon used everywhere else. __Fix__ Use `Switch`, now that it takes a label icon. <img width="400" height="322" alt="image" src="https://github.com/user-attachments/assets/d71580e2-68c2-473e-8819-ed532ff2f1d8" /> + Community PR: odoo/odoo#286700 task-286528
The Belgian payroll interface now correctly shows the Working Time Reorganisation field on fixed calendars when credit time attendance requires it. This helps payroll users see and manage the relevant information without affecting the intended behavior for variable calendars.
Original PR description
A recent change incorrectly hid the Working Time Reorganisation (MRT) field on fixed calendars, even when a credit time attendance triggered its computation. This commit restores the dynamic visibility of the MRT field for fixed calendars, while preserving the intended behavior for variable calendars. Task: 6538351
This fix ensures Belgian payroll correctly includes canteen cost codes when calculating payslips. It closes a gap from a previous correction, helping payroll results and related validation tests reflect the right employee cost treatment.
Original PR description
Previous fix 9c4acee2d324a454d12dd21388ae083f99c40416 was missing a change in the list of code to read. Forward-Port-Of: odoo/enterprise#130522 Forward-Port-Of: odoo/enterprise#130481
The Sign app now correctly opens the file picker when users tap "Add Document" from a mobile template view. This prevents an error screen and lets users upload PDFs from mobile devices as expected.
Original PR description
Version: - saas-19.5 Steps to reproduce: - Open a Sign template on a mobile. - Go to the Documents tab in the sidebar. - Click "Add Document" to upload a new PDF. Issue: - clicking on "Add Document" button raise a traceback. Cause: - The button called `this.requestFile(...)`, but that method lives on `this.signButtons`, not on the component itself. Solution: - Fix the button to call `this.signButtons.requestFile(...)` so it opens the file picker correctly. task-6535275
When a contact linked to multiple active users is mentioned, all of those users now receive the notification immediately instead of only one seeing it right away. This ensures teams sharing a contact record do not miss timely mention alerts and avoids relying on a page reload to see them.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This happens because the notification is sent on the single user that _notify_get_recipients picks for a partner, and since "[REF] bus, mail: use user rather than partner as bus target" a user is its own bus channel, so the other users of that partner are no longer reached. The notification record is stored per partner, which is why a reload shows it. This commit fixes the issue by sending to every active user of the notified partner. https://github.com/odoo/enterprise/pull/129969 Forward-Port-Of: odoo/odoo#286290 Forward-Port-Of: odoo/odoo#283836
This fixes small icon display issues in the Stock Barcode and Planning Field Service areas. Package and planning-related icons now show as intended, reducing visual confusion for users.
Original PR description
[FIX] stock_barcode: fix `oi_dropbox` typo --- `stock_barcode` uses the `oi_dropbox` icon to represent packages. odoo/enterprise@86659741 made a typo, this commit fixes it. task-6377407 [FIX] planning_field_service: fix some remainings fa icons --- task-6377407
The update adjusts an internal test expectation for France-specific employee leave management so it aligns with newly added DRS automation. This helps keep automated checks reliable without changing day-to-day user functionality.
Original PR description
Related to odoo/enterprise#129851 This commit adapts a query counter in order to fit with the newly integrated DRS automation task-5915160
This update corrects several records and tests that used values longer than allowed by their configured field limits. It helps avoid validation errors and keeps accounting, payroll, localization, and point-of-sale data consistent with system rules.
Original PR description
https://github.com/odoo/odoo/pull/286488
When a partner is mentioned, all active users connected to that partner now receive the notification immediately instead of only one user seeing it before reload. This improves reliability of real-time communication, with related test updates to reflect the extra processing needed.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This commit raises the query counts of the activity tests: the fix in odoo resolves each notified partner to its active users, which costs one query per post with an inbox recipient. https://github.com/odoo/odoo/pull/283836 Forward-Port-Of: odoo/enterprise#130206 Forward-Port-Of: odoo/enterprise#129969
Users can now access the correct reconciliation models from bank statement lines when the bank journal uses a foreign currency. This fixes a search issue where currency labels in journal names prevented matching models from appearing, helping accounting teams manage bank reconciliation setup reliably.
Original PR description
### Issue before this commit: When clicking "Manage Models" from a bank statement line, the associated reconciliation models are not displayed when belonging to a foreign currency journal. ### Steps…
### Issue before this commit: When clicking "Manage Models" from a bank statement line, the associated reconciliation models are not displayed when belonging to a foreign currency journal. ### Steps to reproduce the issue: 1. Download Accounting 2. Go to Currencies and activate another currency like EUR 3. Go to Journals and create a new one with bank type and curency EUR 4. Go to dashboard > new test bank journal created > 3 dots in the upper-right corner > Models > create a new one (ex Tester) setting the new test bank created as journal 5. Go to test bank journal and create a new bank matching 6. After the line is created click the 3 dots and go to Manage Models 7. See that the new model Tester created does not appear ### Cause of the issue: Foreign currency journals append their currency to the display_name (e.g., "Bank (EUR)"). The JS search framework passes this full decorated string into the search domain. The backend then attempts to match "Bank (EUR)" exactly in the database name and code fields, which fails because the database name is "Bank" without the currency added. https://github.com/odoo/odoo/blob/9c67949be529eb86886b3d5bde08e81e048ecfe7/addons/account/models/account_journal.py#L1095-L1100 ### Reason to introduce the fix: The filter is not working correctly. In this case it's better to change it to a domain instead of a default filter. opw-6481970 Forward-Port-Of: odoo/enterprise#129992
The AI agent panel has been adjusted to follow the same visual style as the Discuss panel. This creates a more consistent experience for users and reduces confusion when moving between collaboration tools.
Original PR description
<img width="2058" height="521" alt="Screenshot 2026-09-07 at 12 26 42" src="https://github.com/user-attachments/assets/c12ba5ec-5dc8-43b0-af10-97b95a24212c" />
A bug in the web interface prevented repeated card reloads from taking effect after the first refresh. This fix ensures cards are recreated properly on every reload, improving reliability for users working with card-based views.
Original PR description
`this.key` is the signal function, so `this.key + 1` concatenates its source and `set` stores that same string on every reload: the first reload changes the key and re-creates the Record, the next ones are no-ops.
This fixes an issue where helpdesk tickets could crash when starting a repair after the product on a return operation was changed. The repair flow now handles unmatched products safely, helping support teams continue processing tickets without interruption.
Original PR description
## Steps to Reproduce: - Install the `helpdesk_repair` module. (with demo data) - Open the ticket titled **"Cabinet Colour and Lock aren't proper"**. - Go to Returns and change the product in Operations. - Click the "**Repair**" button on the ticket. ## Error: `IndexError - tuple index out of range` ## Cause: When the product on the picking does not match the ticket's product, the filtered picking recordset is empty. Accessing `[-1]` on an empty recordset raises an _IndexError_. ## Fix: Use `[-1:]` instead of `[-1]` when retrieving the matching picking, so an empty recordset is handled. sentry-7692929099 Forward-Port-Of: odoo/enterprise#130165 Forward-Port-Of: odoo/enterprise#129526
The payment provider list now shows already installed providers before other available options. This makes the payment setup screen easier to scan and helps users find active providers more quickly.
Original PR description
# How to reproduce - Go to the payment provider Kanban view # The issue The installed providers are listed last, instead of first # Cause This PR changed the way the ordering on Selection fields is processed : https://github.com/odoo/odoo/commit/f0e68e342fb0b1722279cbce4f84161d3f312ac3 It is now based on the index of the current selection in the selection array opw-6537788
Payroll users can now access contract templates and employee type settings as soon as the Payroll app is installed. This fixes a menu visibility issue that previously required an additional salary contract app, making payroll setup clearer and more consistent.
Original PR description
Previously, the contracts configuration menus (Templates and Employee Types) appeared in the payroll configuration menu only if hr_contract_salary was installed. Now, they appear when installing payroll. task-6530076
Fixed an issue where embedded journal-entry actions in Documents could be removed by the cleanup process when users were working in a different company. This helps multi-company users keep their configured document shortcuts intact while preserving company-specific access behavior.
Original PR description
Step to reproduce: - You must have at least 2 companies with an account Journal - Create a New Journal Entry actions (child or parent) - Embed it to a folder - Set your company on a different one than the journal's one - Run the Garbage collector cron (Base: Auto-vacuum internal data) - The embed action has been removed The cause of this is that in the `_get_base_server_actions_domain` method in `documents_account` module there is a check on company to avoid using/running the actions when not in the right company. But the garbage collector don't need to have this check. Task-6147618 Forward-Port-Of: odoo/enterprise#122821
FedEx deliveries can now use a phone number from either the main customer contact or the selected delivery address. This prevents shipments from failing when one related contact record is missing a phone number but the other has it.
Original PR description
Issue ----- Users cannot deliver to a contact's delivery address if the contact address itself doesn't have a phone number. Steps to reproduce ----- - Setup Fedex - Create a contact with no phone number - Create a delivery address for the contact (with phone number) - Create a SO with the contact using Fedex & confirm - Change the partner on the picking to use the delivery address - Validate the picking > Error: missing phone number Cause ----- To populate the `soldTo` part of thepayload, we call `_get_contact_from_partner` with the contact specified on the SO https://github.com/odoo/enterprise/blob/8e60f910a52e3b836e997e54a0b704e5786a28f2/delivery_fedex_rest/models/delivery_fedex.py#L171 https://github.com/odoo/enterprise/blob/8e60f910a52e3b836e997e54a0b704e5786a28f2/delivery_fedex_rest/models/fedex_request.py#L447-L452 The phone number is then taken directly from the contact. ----- Ticket: opw-6427962 Forward-Port-Of: odoo/enterprise#127434
Fixed an issue where completed field service shifts linked to sales orders could incorrectly reset planned hours to zero. This prevents completed work from being shown as still needing planning, improving visibility of scheduling progress.
Original PR description
## before: When marking a shift linked to SO as complete. The `allocated_hours` of this shift is reset to 0. So when the `Planned` button tries to compute the `planning_hours_planned` it adds zero to the planned hours, making all the hours go to the `To Plan`, which is incorrect ## after: prevents the `allocated_hours` from being recomputed when making the shift as complete to avoid this issue. This will leave the hours to be calculated in the `Planned` stat button instead --- task-6425357 Forward-Port-Of: odoo/enterprise#129833 Forward-Port-Of: odoo/enterprise#126396
The messaging menu dropdown no longer shows extra rounded borders that were not intended in this view. This keeps the interface visually consistent and avoids a distracting layout issue for users.
Original PR description
In [1], discuss styling was adapted to frost, adding border radius to the messaging menu. However, borders/radius shouldn't be applied to messaging menu in dropdown. [1]: https://github.com/odoo/odoo/pull/285383 |Before|After| |-|-| |<img width="500" alt="image" src="https://github.com/user-attachments/assets/2fbff5eb-4282-4a5b-88d6-4c3c491dd2ea" />|<img width="500" height="691" alt="image" src="https://github.com/user-attachments/assets/7349b06f-2ddf-4d47-868b-7a2a8ccfc6b7" />|
Payslip worked-day lines are now translated using the employee's payslip language instead of the HR officer's language. This prevents mixed-language payslips and helps employees receive clearer, more consistent payroll documents, except where translations are not yet available.
Original PR description
l10n_be_hr_payroll Translation for payslip was not uniform. It is supposed to be based on employee language. But some fields we based on the user language (the HR officer who issues the payslips) What is not covered : fields that have missing translations. Those ones will still appear with the default (english) value.
Fixed an issue where exporting time entries could fail for employees whose contract had multiple versions. This helps payroll users complete exports reliably after contract changes without encountering an error.
Original PR description
## Steps to Reproduce: - Install the hr_work_entry module. - Create an employee. - Payroll tab > create a contract by setting only the start date (leave the end date empty). - From the contract…
## Steps to Reproduce:
- Install the hr_work_entry module.
- Create an employee.
- Payroll tab > create a contract by setting only the start date (leave the end date empty).
- From the contract version timeline (navigation bar), click the "+" button and create a new version.
- Open the cog menu (gear icon) and click 'Export Time Entries'.
## Error:
`ValueError - Expected singleton: hr.version(257, 258)`
## Cause:
Method `_get_contract_versions()` returns multiple versions for the given period.
for example:
`contract_dict = {datetime.date(2026, 8, 1): hr.version(1, 2)}`
The code assumes each value is a singleton and builds the recordset using `c.id`,
`[c.id for c in contract_dict.values()]`
Since `c` contains multiple records, accessing the ID will raise an error.
## Fix:
Instead of accessing `id`, it will access `ids`, and it returns the list of all records (`[1, 2]`).
`chain.from_iterable()` flattens this list into one iterable sequence `(1, 2, ...)`, and
then it will convert into a list and be passed to `browse()` to fetch the corresponding recordset.
sentry-7623869169
Forward-Port-Of: odoo/odoo#278858Custom font files uploaded through the website editor no longer appear in the media dialog's Documents tab. This keeps the document list cleaner by hiding technical font-related files that business users do not need to manage there.
Original PR description
Steps to reproduce: - From the website editor, open the Theme tab. - Upload a custom font. - Open the media dialog and go to the "Documents" tab. Issue: The uploaded font files appeared in the…
Steps to reproduce:
- From the website editor, open the Theme tab.
- Upload a custom font.
- Open the media dialog and go to the "Documents" tab.
Issue:
The uploaded font files appeared in the Documents tab. When a zip file
was uploaded, every font it contained appeared individually, along with
the generated "CSS font face" attachment and the Google fonts metadata
cached by the server.
Cause:
Fonts uploaded through `/website/theme_upload_font` are created as
public attachments. The Documents tab of the media dialog lists every
public attachment that is not an image or an asset, so the font files
(mimetype `font/...`), their font face declaration (mimetype `text/css`)
and googleFontMetadata (server caches it as public attachment) were
listed.
Fix:
Create those attachments with a technical `/web/font/{id}/{name}` url
and exclude it from the Documents tab domain.
Existing databases are adapted by an upgrade script(https://github.com/odoo/upgrade/pull/10999)
Upgrade PR: https://github.com/odoo/upgrade/pull/10999
task-[4771523](https://www.odoo.com/odoo/project/974/tasks/4771523)This fixes an issue where special styling from user mentions could accidentally be carried into email content. Emails generated from Odoo will now keep cleaner, more consistent formatting and avoid a test failure caused by differing style values.
Original PR description
Before this commit, inlining the styles of a mail body copies the border radius, the padding and the margin of a mention into its style attribute, although `o_mail_redirect` is blacklisted so that none of its class styles are inlined. This happens because the blacklisted declarations are matched by property name, while the styles collected for the node have `padding-top` and its siblings merged into `padding`, `margin` and `border-radius`, three names no blacklisted declaration carries. This commit compares each blacklisted declaration with the value the node ends up with, so that a merged shorthand is removed as well. Note that the three tests asserted the values that leaked, the radius among them being `$btn-border-radius-lg`: 6px in enterprise but 4px in community, which is what turned the JS suite red on master. https://runbot.odoo.com/odoo/error/946970
Corrects how the website shop reads the delivery country when searching for pickup locations. This prevents pickup point lookup from failing or showing an incorrect prompt when a customer address already has a country selected.
Original PR description
`country_id` is a number so the fix in #281720 - which avoids a traceback when no country is present - now leads to nothing being loaded when the delivery address has a country. Because `country_id?.id` now gives `undefined`. The fix makes sense only if the field is marked as a many2One as done in 319bb52 (which was only merged in 19.4+). This is consistent with fix edf65dc done in 19.4+ as well. Forward-Port-Of: odoo/odoo#286195 Forward-Port-Of: odoo/odoo#285006
This update fixes missing accent marks in Spanish fiscal position labels. It improves the professionalism and accuracy of Spanish localization text without changing business logic or workflows.
Original PR description
@Tecnativa Forward-Port-Of: odoo/odoo#284053
Links added to manufacturing shop floor notes now open in a new browser tab instead of disrupting the current shop floor view. This keeps operators in their workflow while still allowing them to access attached documents or referenced pages.
Original PR description
Steps to reproduce 1. On a Manufacturing Order, open the Miscellaneous tab, click in Additional Notes, type "/file", pick "File" (Insert a file from Documents), select a document and save. 2. Open…
Steps to reproduce 1. On a Manufacturing Order, open the Miscellaneous tab, click in Additional Notes, type "/file", pick "File" (Insert a file from Documents), select a document and save. 2. Open the Shop Floor of that Manufacturing Order. 3. On the order card, click the link shown in the note. Expected: the link opens in a new tab. Actual: the Notes edition dialog opens and the link is not opened. Issue --- On the Shop Floor the Additional Notes HTML field is rendered inside a container whose click handler opens the note edition dialog, its links carry no target and the handler stops the event propagation, so clicking a link opens the edition dialog instead of the linked document. Additional Notes became an HTML field in ebc30649c0f5, which allowed such links while this rendering was never adapted to open them. https://github.com/odoo/enterprise/blob/bfda5100ddd423f9e5fb91a9f83b4719c1f58397/mrp_workorder/static/src/mrp_display/mrp_display_record.xml#L58-L63 The note links now receive target="_blank" after mount and on every patch so they open in a new tab like the readonly HTML field viewer, and the container handler ignores clicks landing on a link so it no longer opens the edition dialog for them. https://github.com/odoo/enterprise/blob/bfda5100ddd423f9e5fb91a9f83b4719c1f58397/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L106-L111 opw-6487702 Forward-Port-Of: odoo/enterprise#128979
This update prevents conflicting context settings when users create items quickly during bank reconciliation. It ensures the user's current settings take priority, reducing inconsistent behavior in accounting workflows.
Original PR description
Since this commit: https://github.com/odoo/enterprise/commit/938978c622700f9de097d9ff163f5b3c043231ed We pass the auto_statement_processing context key to false when destroying the component. The problem is that for the quick creation we use the model context. It might happen that those two contexts are different and can create inconsistancy. This commit will make sure the user context has priority on the global state context. no task id Forward-Port-Of: odoo/enterprise#130456 Forward-Port-Of: odoo/enterprise#129957
This fix ensures that when an employee has multiple contracts and payslips in the same month, canteen costs are applied to the first payslip with a paid amount. This helps Belgian payroll calculations stay accurate and avoids misplaced employee cost deductions.
Original PR description
In case of multiple contracts for a single month (and then multiple payslips), the canteen cost must appear in the first payslip that have a paid amount. Forward-Port-Of: odoo/enterprise#130364 Forward-Port-Of: odoo/enterprise#130109
Belgian CodaBox SODA imports now use the actual last import date when checking for new statements, instead of relying on accounting entry dates. This prevents valid payroll statements generated within the same accounting period from being skipped.
Original PR description
Before v19.1, we used to set the date on the journal entry based on the generation date of the SODA statement during the import. So it was possible to use the last date found in the salary journal as a `date_from` filter when fetching new SODA statements. Starting from v19.1, we now set the date on the journal entry as the last day of the accounting period referenced in the SODA file. However, we didn't change the fetching logic accordingly. If a SODA statement is generated on July 7 for the accounting period of July, the date on the journal entry would be July 31 and, consequently, any other SODA statement generated in-between those dates would be filtered out during the fetch. Ticket: opw-6214589 Forward-Port-Of: odoo/enterprise#130183
This fix prevents an unexpected error from appearing when Odoo handles certain report actions. It improves reliability by using the correct record context, reducing the chance of users seeing a traceback during normal operations.
Original PR description
opw-6360013 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#274977
The stock allocation report has been refined to work better on mobile, avoid over-allocating already reserved quantities, and prevent errors from repeated quick actions. Users can now allocate or unallocate directly from the forecast report, while validation flows no longer open the allocation report automatically.
Original PR description
This PR fixes issues with [the recently merged](https://github.com/odoo/odoo/pull/264299) allocation report. Main changes are: - Add specific design for mobile device; - Don't allocate already reserved quantity; - Allocation report won't open itself automatically when validating an operation from the Barcode app, no matter the configuration (a setting is planned to be added in `master` to let the possibility if the user wants); - Add the possibility to allocate from the forecast report. For more details on these changes or other fixes, check the corresponding commit's message. _________ **Enterprise PR:** odoo/enterprise#122258 task-4894566 Forward-Port-Of: odoo/odoo#272722
The barcode app’s print button now prints labels for the allocated products instead of the allocation operation report. This helps warehouse users get the right labels directly from barcode lines, reducing confusion and manual reprints.
Original PR description
Before this commit, the print button on barcode line printed the allocated operation's report instead of the allocated products' labels. This commit fixes that. _________________ **Community PR**: odoo/odoo#272722 [task-4894566](https://www.odoo.com/odoo/966/tasks/4894566) Forward-Port-Of: odoo/enterprise#122258
Fixes an error that could occur when paying a vendor bill with withholding tax after the currency field was cleared. The system now safely falls back to the company currency, helping users continue the payment flow without an unexpected crash.
Original PR description
Currently, an error occurs when user tries to pay on a vendor bill and removes the currency. Steps to replicate: - Install `l10n_account_withholding_tax`and activate multiple currencies. - Open…
Currently, an error occurs when user tries to pay on a vendor bill and removes the currency.
Steps to replicate:
- Install `l10n_account_withholding_tax`and activate multiple currencies.
- Open Invoicing > Vendors > Bills and create a new bill and add a vendor and bill date.
- Add a product and tax `2% WTH`.
- From the Cog menu > Click Pay > Remove the Currency.
Error:
```
File '/home/odoo/src/odoo/saas-19.4/addons/l10n_account_withholding_tax/models/account_withholding_line.py', line 208, in _compute_original_amounts
line.original_base_amount = line_curr.round(base_amount * rate)
File '/home/odoo/src/odoo/saas-19.4/odoo/addons/base/models/res_currency.py', line 264, in round
self.ensure_one()
File '/home/odoo/src/odoo/saas-19.4/odoo/orm/models.py', line 5342, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: res.currency()
```
Cause:
- As the user removed currency, the `comodel_currency_id`is received as false.
- Later when we call `round()` on the empty res.currency recordset causes this error to occur.
Solution:
- Added the company currency as a fallback value when `currency_id` is removed by user, since `currency_id` is a required field user will need to select a currency when saving.
sentry-7616890592
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283737
Forward-Port-Of: odoo/odoo#277507This fixes an internal test setup for LDAP authentication so it matches expected cookie behavior after recent timezone handling changes. It helps keep automated checks reliable without changing how users sign in.
Original PR description
In #279318 `ResUsers._login` was modified to *parse* the `tz` cookie instead of just storing it in order to normalize the timezone (as browsers can send CLDR timezones which are legacy tzdata timezones). This is a problem in auth_ldap's tests because `mock_check_identity` sets the entire request as a straight mock, so `request` is truthy, `request.cookies` is a mock, `request.cookies.get(...)` is a mock, and `ZoneInfo` blows up trying to resolve it because it's nonsensical. If we make the mock cookies into a straight dict, `request.cookies.get(...)` returns `None` and we skip ahead without error (previously we'd skip ahead because `tz in all_timezones` would be `False`). https://runbot.odoo.com/odoo/error/945680
Adds checks before sending Turkish Nilvera e-invoices so users are warned when invoice lines are missing required taxes or product/CTSP details. This helps prevent invoices from being rejected by Nilvera, while avoiding unnecessary warnings for note or section lines.
Original PR description
Nilvera does not accept invoices with lines that do not have taxes, so we added a valiation check for sending the invoice to warn the user. Additionally, we raise a warning when a line does not have a product and has an empty CTSP. However, if the line is a note or section, this warning should not be triggered. task-6404409 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#284969 Forward-Port-Of: odoo/odoo#284377
Restarting a live chat chatbot session now correctly shows the available answer choices again. This prevents visitors from getting stuck or confused when they restart a conversation before it has been fully saved.
Original PR description
Before this commit, after restating a chabot session, the chabot question answers were not shown. This happens since the change in [1], introducing the field `selectedAnswerEver` in order to solve problems of stale server writes. However when a session is restarted, the first chatbot steps without a "real" message record (before the session is persisted) resolve to the same records of the earlier session. In turn this leads to said step having a selected answer already and thus not showing the choice. This commit solves the issue by clearing the selected answer fields when going to the next step, which is acceptable against stale writes since it's a purely client side decision. task-6535116 [1] https://github.com/odoo/odoo/pull/278597
Turkish credit notes created from existing invoices now use the dedicated sales return account from the sales journal instead of incorrectly keeping the original sales account. This improves accounting accuracy for Turkish companies while preserving exact matching for cancellation reversals.
Original PR description
The Turkish chart of accounts keeps sales and sales returns on separate accounts, and the sales journal carries the account to use for returns. A credit note typed in by hand already lands on it, but one created from an existing customer invoice did not. Reversing an invoice copies `account_id` over from the invoice line, and since that field is a stored compute without depends, nothing ever recomputes it, so the return kept the sales account. Set the journal account on the copied product lines instead. Reversals made to cancel an entry are left alone, as those have to mirror the original move exactly for the two to net out, and a plain duplicate is untouched. Task-6438412 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284808 Forward-Port-Of: odoo/odoo#282858
E-invoice imports and exports no longer include internal deferred revenue dates that are only relevant to the vendor's accounting process. This prevents customers from receiving irrelevant date information and avoids creating deferred entries when importing vendor bills.
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). task-6014315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281348 Forward-Port-Of: odoo/odoo#265796
Pasted tables from Google Docs now keep only the first row as the header, matching what the editor supports. This prevents extra header rows from appearing incorrectly and makes pasted table content more consistent for users.
Original PR description
Steps to Reproduce - Copy a table with multiple header rows from Google Docs. - Paste the table into the editor. Description of the issue: - The pasted table contains multiple header rows, but the editor supports only the first row as the table header row. Cause: - During paste, `cleanForPaste` does not handle tables with multiple header rows - As a result, header cells (`<th>`) in rows other than the first row remain as header cells instead of being converted to normal table cells (`<td>`). Solution: - Update `cleanForPaste` to handle tables with multiple header rows. - If a table contains `<th>` elements in any row other than the first row, replace those `<th>` elements with `<td>` elements. - This ensures that only the first row is treated as the table header row. task-6455248 Forward-Port-Of: odoo/odoo#286303 Forward-Port-Of: odoo/odoo#281234
Fixes a Razorpay FPX payment issue that could cause checkout to fail when customers returned from the payment page. The payment flow now handles missing return details correctly, improving reliability for merchants using Razorpay FPX.
Original PR description
Issue: --- Paying with Razorpay using FPX raises `KeyError: 'amount'` when the customer returns from checkout. Steps to reproduce: 1- Enable Razorpay with FPX as a payment method. 2- Pay an order using FPX. Cause: --- In FPX, Razorpay returns without `amount`/`currency`. `_apply_updates` fetches the full payment from the API to determine the state, but that fetched entity is local to the method and never reused for amount validation, so `_process` still calls `_validate_amount` / `_extract_amount_data` with the original, amount-less redirect data. This issue is introduced after c34992ffd94ba4594731400839332b677fdc2b32, which removed the check in `_extract_amount_data` that returned `None` (skip validation) when `amount`/`currency` were absent. opw-6467815 Forward-Port-Of: odoo/odoo#286476
Stripe SEPA payments no longer use the order reference as the bank statement descriptor, avoiding failures when an order number contains only digits. The descriptor now uses the company name again, making SEPA payments more reliable for affected customers while preserving expected statement information.
Original PR description
**Steps to reproduce:** 1. Install Sales, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install Sales, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Create a sale order with a name that doesn't include any characters (numbers only), confirm, click preview and attempt to make a payment using SEPA **Issue:** `The statement descriptor must contain at least one Latin character.` **Cause:** The previous fix (4fde0232b821c9a1d46d589ff14495f4e19029f4) passed the order reference directly, assuming it will contain characters. The intended behavior is to actually have the company name used in the statement descriptor field: https://support.stripe.com/questions/what-is-a-statement-descriptor-and-how-do-i-update-it This was the existing behavior before the fix, so will revert back to it. opw-6497127 Forward-Port-Of: odoo/odoo#286620 Forward-Port-Of: odoo/odoo#286287
Colombian retention reports now calculate the taxable payment amount correctly when vendor bills include partial credit notes. This prevents credit notes from incorrectly increasing the reported tax base, improving accuracy for retention certificates and related tax reports.
Original PR description
**STEP TO REPRODUCE** 1. install l10n_co_reports and account_accountant 2. Create a bill, with a line with a retention tax (3.50% RteFte). 3. Create a partial credit note (unit price less than what's on the bill). 4. Goes to the report 'Certificado de Renteciòn en Fuente', and notice the Monto del Pago Sujeto Retenciòn is not correct. **CAUSE** The sql query multiply tax_base_amount by -1 if debit > 0, which means (because we are dealing with vendor bills) the line is from a credit note, but tax_base_amount is already a signed value so credit notes ends up contributing to the tax base amount while they should reduce it. opw-6235830 Forward-Port-Of: odoo/enterprise#130340 Forward-Port-Of: odoo/enterprise#119716
Invoice import and export now avoids using internal deferred revenue dates that are only relevant to the vendor. This prevents customers from receiving irrelevant accounting dates in Peppol invoice data while preserving the needed Colombian support document behavior.
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). But it is kept for the colombian localization in case of support documents though. task-6014315
This fix makes employee records with the same name appear in a consistent order, preventing intermittent test and data-ordering failures. It helps ensure HR-related absence information is read reliably when a partner is linked to multiple users.
Original PR description
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main…
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main user of the partner This happens because the test reads the first entry of the hr.employee list, which holds one employee per user of the partner: back on the 7th for the main user, on the 6th for the other. This comes from "[FIX] hr*: load out-of-office dates from all user employees", which added the employees of the partner to the payload, where it held those of the main user only. The problem is that the list keeps the order of employee_ids, which is 'name' with no tiebreaker, and both employees are named test1, as an employee takes the name of its user and creating the second user renames the partner. Postgres is then free to return either one first, and the failing builds get the second one. This commit fixes the issue by ordering the employees on 'name, id', so that employees sharing a name keep a stable order instead of the one the database picks. The test asserts the whole hr.employee list, one entry per user of the partner, rather than its first entry alone, and that assertion pins the order. https://runbot.odoo.com/odoo/error/945994 Forward-Port-Of: odoo/odoo#286796 Forward-Port-Of: odoo/odoo#286236
Changing Peppol Reception Mode to receive invoices as documents no longer triggers an error. This helps Belgian companies using Peppol complete setup smoothly without interruption.
Original PR description
Steps to reproduce: - Install `documents_account_peppol` and `l10n_be` module - Switch to BE Company > `Activate Peppol` - Change `Peppol Reception Mode` -> `Receive as Documents` Traceback: `AttributeError: 'res.company' object has no attribute '_peppol_allows_document_reception'` Problem: Changing the `Peppol Reception Mode` to `Receive as Documents` causes an `AttributeError` because `_compute_peppol_purchase_journal_required()` calls `_peppol_allows_document_reception()` on `config.company_id`, but the method is defined on `res.config.settings`. Cause: The method is available on the `res.config.settings`, not on the `res.company`. Solution: Add `_peppol_allows_document_reception()` method in `res.company` and call company's method from the `res.config.settings` method. opw-6470552 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286517
This update fixes an internal test issue in the Mail app where mention styling could be measured differently depending on the installed edition. It helps keep automated checks stable across Odoo setups without changing the user experience.
Original PR description
Before this commit, some tests in convert_inline were failing due to mismatch of border-radius of mentions: - expected 0.375rem - received: 0.25rem This happens because the border radius of mention relies on `$btn-border-radius-lg`, which has different value in community and enterprise, respectively `o-to-rem(6px)` and `o-to-rem(8px)`. This commit fixes the issue by dynamically reading the border radius of mention, so that running it with or without enterprise modules make the test pass. Fixes runbot-error-946970
Fixed an issue in Documents where choosing “Search More...” from fields like Owner or Customer could immediately close the selection window. Users can now interact with that window normally, making it possible to search, sort, and select the right related record without interruption.
Original PR description
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the…
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the field dropdown, click "Search More..." to open a modal dialog. 5. Click inside the "Search More..." modal (e.g., to sort columns or resize headers). Issue: - The modal dialog immediately closes, and the contact cannot be selected. Root cause: - When an inspector field is edited, the record row is put into edit mode. While in edit mode, the documents list renderer listens for global clicks. Clicking inside the "Search More..." modal dialog targets elements that have `.o_list_renderer` (since the modal dialog renders a list view). Because the click target is within a list renderer but is not a document row, `DocumentsListRenderer.onGlobalClick` executes and clears the selection of the main list view. Clearing the selection unmounts the edited field in the inspector, thereby destroying the modal dialog stack. Solution: - Modify DocumentsListRenderer.onGlobalClick to scope click handling to the current Documents list renderer. Ignore clicks outside this.root.el, so interactions in nested UI such as Search More... do not clear the main selection and destroy the inspector field. opw-6253360 Forward-Port-Of: odoo/enterprise#128812 Forward-Port-Of: odoo/enterprise#119262
Manual quality checks created from a picking can now record a partial failed quantity without blocking the transfer. This prevents validation errors and lets warehouse teams continue processing orders when only some units fail inspection.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `quality_control` module - Create a picking order with a product - From the gear menu, create an on-demand Quality Check -…
Version:
--------
- 19.0+
Steps to reproduce:
-------------------
- Install `quality_control` module
- Create a picking order with a product
- From the gear menu, create an on-demand Quality Check
- Set the check to *Control per Quantity* and back to the picking
- Set the done quantity to 10
- Open the Quality Check wizard
- Try to fail 3 units
Issue:
------
Validating the partial failure raises a `ValidationError`:
- Missing required value for the field 'Team' (team_id)
The quality check split is not performed and the picking cannot be processed.
Cause:
--------
Quality checks created on-demand from the picking (via the gear menu) have
no associated `quality.point` or `stock.move.line` — only
`picking_id` is set at creation time.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L457
In `_move_to_failure_location()`, the `move_line` branch assumes
`check.move_line_id` is populated. Since it is empty for on-demand
checks, the split logic operates on an empty recordset.
The new quality check for the split is then created via:
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L493
At this point both `failed_move_line` (a copy of the empty move line) and
`check.point_id` are empty. `_get_check_values(False)` cannot derive
fields normally sourced from the quality point (`team_id`, `company_id`,
`measure_on`, `test_type_id`, etc.), causing the `ValidationError` on record creation.
Fix:
----
- If the quality check is not linked to a move line, find the matching move line
from the picking before splitting the failed quantity.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/stock_move_line.py#L94-L97
- `_get_check_values()` normally takes values from a Quality Point.
Since on-demand quality checks do not have one, fill the missing
values (`team_id`, `measure_on`) from the original quality check instead.
This allows manually created quantity-based quality checks to be
split correctly after a partial failure.
---
opw-6428749
Forward-Port-Of: odoo/enterprise#130275
Forward-Port-Of: odoo/enterprise#126505This update removes an older Point of Sale data cleanup step that is no longer needed. A newer, more targeted fix now handles stale loyalty reward lines, reducing the risk of unintended changes while keeping checkout data clean.
Original PR description
This fix is no longer required(https://github.com/odoo/odoo/pull/202752) as this one (https://github.com/odoo/odoo/pull/257043) is cleaner and less aggressive (it will only delete stale reward lines). This is the relevant part of the new fix to delete the previous one: https://github.com/odoo/odoo/pull/257043/changes#diff-18cef42f8c39513a82387e9cb81bc732b252304cd15b5b2f7b0b4623ac20cb41R100-R104 opw-6447092 Forward-Port-Of: odoo/odoo#286499 Forward-Port-Of: odoo/odoo#285376
Fixed an issue where importing multiple Belgian SODA files at once could copy accounting lines from the first file into the second. This helps ensure imported payroll accounting data stays accurate and avoids duplicate or incorrect entries.
Original PR description
Due to this commit: https://github.com/odoo/enterprise/commit/93c05b380e3c939e3c0b44eafcd7a41e86042d2d When importing 2 sodas from drag and drop. Due to the placement of the line_ids variable, the second move would have the line of first. By placing the variable in the loop we don't have that problem anymore task-6528101 Forward-Port-Of: odoo/enterprise#130190
This fix makes internal automated tests use a consistent language when checking activity history and tracking messages. It helps prevent false test failures caused by translation differences, improving release reliability without changing day-to-day product behavior.
Problem: When a parent element applies a `font-weight: 300` to its content, a child `<strong>` tag defaults to `font-weight: bolder`, which resolves to a computed font weight of `400`. For certain font families, weight `400` is visually identical to `300`, leaving no visual distinction for bold text. Cause: `<strong>` tags relied on relative weight boosting (`bolder`), which only increases the parent weight from `300` to `400` instead of applying explicit bold weight. Solution: Expl
Original PR description
Problem: When a parent element applies a `font-weight: 300` to its content, a child `<strong>` tag defaults to `font-weight: bolder`, which resolves to a computed font weight of `400`. For certain font families, weight `400` is visually identical to `300`, leaving no visual distinction for bold text. Cause: `<strong>` tags relied on relative weight boosting (`bolder`), which only increases the parent weight from `300` to `400` instead of applying explicit bold weight. Solution: Explicitly set `font-weight: bold` on `strong` for `.o_wblog_read_text` Steps to reproduce: - Go to /blog - Open any blog - Open editor. - Select some text from the content of the blog. - Apply Bold. - Observe that there is no visual difference. opw-6460699 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282667
The Shopee sales integration now continues processing shipment label batches even if one batch has incomplete or unexpected data from Shopee. This reduces failed background jobs and helps remaining shipments keep moving without manual intervention.
Original PR description
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch shipment labels for multiple batches of shipments. If some shipments do not contain the required data in the Shopee API…
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch
shipment labels for multiple batches of shipments. If some shipments do not
contain the required data in the Shopee API response, the error causes the
cron to stop, preventing the remaining batches from being processed.
Error:
`ValueError: KeyError('status') while evaluating 'model._sync_shopee_pickings()'`
This issue was introduced by a recent refactoring commit [1] focused on linting
and formatting the Python file. The commit replaced the generic `Exception`
with `UserError` when handling errors during batch label printing.
As a result, errors other than `UserError` are no longer handled at the batch
level. When such an error occurs, the entire cron process stops instead of
failing only the affected batch and continuing with the remaining batches.
This commit fixes the above issue by handling generic `Exception` during
shipment label generation, ensuring that the error is handled for the
affected batch while the remaining batches continue to be processed.
[1]: https://github.com/odoo/enterprise/commit/cfe5d947579739ad770ac3f1525ce157af530846#diff-e072c3ecf980add685bb4a4f25cf2b0ab5d4625988e4afc2c4d4faeae687ca88R199
sentry-7685943988
Forward-Port-Of: odoo/enterprise#130295
Forward-Port-Of: odoo/enterprise#130181