Monday, August 24, 2026
45 changes · saas-19.4
Enhancements to existing features
Mail activity and message searches now load records in smaller chunks when a limit is used. This helps views open reliably while still applying access rules, avoiding cases where simple screens could fail because too much data was loaded at once.
Original PR description
When a limit is applied in the search method, fetch the data in small batches like we do in ir.attachment. This allows to search with a limit on views while applying security access. Without this, simple views cannot be opened because the ORM searches for all records before filtering them in memory. Note that this cannot be avoided for group by queries and that if we don't set a limit, we will eventually still fetch everything in smaller batches. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265203
Odoo restores the default grouping option in the search area for affected views. This helps users keep familiar list organization behavior and avoids disruption from the previous removal.
Original PR description
This reverts commit 7413e08c166ef3123ac7ed6623db1fb366f44e3c (#265574) task-6425644
Administrators can now see and adjust whether each time off type creates a Calendar entry when employees submit leave requests. This makes the existing option easier to manage and helps companies control how absences appear in shared calendars.
Original PR description
The `create_calendar_meeting` field on `hr.leave.type` allows users to choose if leave requests created with a given time off type generate a corresponding entry in the Calendar app. However, this field was not displayed on the form view. This commit adds `create_calendar_meeting` to the `hr.leave.type` form view inside the configuration section, along with dedicated help text explaining its behavior. Task: 6445794 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283450
The website configurator now clearly names the color palette selected by the AI recommendation. This helps users understand the suggested branding choice and why it fits their business context.
Original PR description
Steps to reproduce: - Start website creation with the configurator. - Reach the color palette selection step. => The AI recommendation does not name the selected palette. Before this commit, the recommendation described suitable colors without identifying the corresponding palette. After this commit, the recommendation names the selected palette and explains why it fits the business context. task-6484260
This update adds automated checks to catch outdated code patterns that could silently break parts of the interface after a framework upgrade. It also updates the mail chatter composer to use the current pattern, reducing the risk of users encountering unexpected behavior.
Original PR description
Owl 3's useEffect takes a single callback and calls it with no arguments, but Owl 2 code still parses and runs. `useEffect(fn, () => [deps])` silently drops the dependencies, and `useEffect((el) => ...)` gets undefined parameters - nothing fails until a user walks the path. Add two no-restricted-syntax selectors so eslint catches both on the lint build. They are wrong by construction, so no exceptions are needed, and the useLayoutEffect shim keeps its two arguments under a different callee name. The rules go in test_lint/tests/eslintrc and, for point_of_sale, iot and obox, in web/tooling/_eslintrc.json. The chatter composer patch is the last community call site of that shape. Its body already reads both recipient lists, so dropping the dependency argument is enough; it matches master, so the forward-port is a no-op. Enterprise: https://github.com/odoo/enterprise/pull/128751
Stock quantity updates now avoid repeating the same warehouse lookup when processing several products at once. This reduces unnecessary database work during batch operations and can make inventory updates run more efficiently.
Original PR description
When `_inverse_qty_available` processes multiple products, it performs the same warehouse search for every eligible product, resulting in redundant queries during batch operations. Look up the warehouse lazily once and reuse it for all products in the recordset. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283564
Canceled point-of-sale orders using the Belgian black box no longer hold up the checkout flow while waiting for receipt printing. This helps staff move on faster when an order is canceled, reducing unnecessary delays at the register.
Original PR description
Stop awaiting the receipt print in the POS for canceled orders task-id: 6425204 Forward-Port-Of: odoo/enterprise#128593
Resolved issues and error corrections
The HTML editor now places the drag-and-drop move handle on the correct side when editing right-to-left content. This makes block editing more intuitive and consistent for users working in RTL languages.
Original PR description
Problem: In MoveNodePlugin, `setMovableElement` sets the position of the drag-and-drop handler without considering `this.config.direction === "rtl"`. The handler is placed on the left side regardless of text direction. Solution: - In RTL mode, calculate the handle position from the right edge of the element so it is placed on the right side with the same distance as in LTR. - Update hover hooks, editable bounds, and dropzone rectangles for RTL mode. Steps to reproduce: 1. Open the editor in RTL mode. 2. Hover over a movable block element (e.g. `<p>`). => The move handle appears on the left side of the element instead of the right. task-6442717 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283662 Forward-Port-Of: odoo/odoo#281249
Documentation and clarification updates
A contributor has submitted their Individual Contributor License Agreement for Odoo. This is a legal documentation update that helps ensure future contributions can be accepted under the project’s licensing requirements.
Original PR description
This pull request submits my Odoo Individual Contributor License Agreement signature. Forward-Port-Of: odoo/odoo#282045
This fixes an issue where store pickup orders marked as pay-on-site were treated as already paid, so they did not appear for fulfillment in the Point of Sale order list. Pay-on-site amounts are now excluded from the unpaid amount calculation used by POS, making these orders visible and easier for staff to process.
Original PR description
Step To Reproduce: - install `sale_management` and `website_sale_collect` and POS with demo - go to shop page, add a product -> checkout - Use `Pick Up in Store` feature and `Pay on site` payment…
Step To Reproduce:
- install `sale_management` and `website_sale_collect` and POS with demo
- go to shop page, add a product -> checkout
- Use `Pick Up in Store` feature and `Pay on site` payment method -> confirm
- notice a Sale order is created for this
- Open POS, try to fulfill the linked SO, by clicking on `Quotation/Order`
Observation:
- The SO is not visible in the list view
Cause:
- clicking on `Quotation/Order` initiates a search with domain `["amount_unpaid", ">", 0]`
https://github.com/odoo/odoo/blob/21e3b547e486951421e39733c19a8a2d54361e00/addons/pos_sale/static/src/app/components/screens/product_screen/control_buttons/control_buttons.js#L16
- `amount_unpaid` depends on `amount_paid` which is sum of all transaction in ("authorized", "done") state
https://github.com/odoo/odoo/blob/21e3b547e486951421e39733c19a8a2d54361e00/addons/sale/models/sale_order.py#L913-L916
- after commit [1], transactions with payment method of type `postpaid` are considered as `done` (`Pay on site` is postpaid)
https://github.com/odoo/odoo/blob/21e3b547e486951421e39733c19a8a2d54361e00/addons/website_sale_collect/models/payment_method.py#L9-L14
https://github.com/odoo/odoo/blob/21e3b547e486951421e39733c19a8a2d54361e00/addons/payment_custom/models/payment_transaction.py#L40-L41
- this makes `amount_paid ` to be full order amount and `amount_unpaid = 0` for the order and search fails in pos
[1] https://github.com/odoo/odoo/commit/9d01784fa9980fb9e4989e6e4e9f35909665e6ca
Fix:
- Fix the compute of `amount_unpaid` and do not count transactions amount from
postpaid payment method
Note: issue occurs for POS only, hence, we avoid changing anything from sale side
while keeping changes to minimum
opw-6424288
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix ensures Odoo correctly recognizes when the email queue process is running as a scheduled job, so progress tracking works as intended. It also adds clearer logging of the email sending limit to help support teams investigate silent email queue failures linked to memory limits.
Original PR description
The changes introduced by https://github.com/odoo/odoo/commit/19d5367862528979abdcd411095f18d36bdbe7b8 aimed at aligning the mailing cron job logic with the new `_commit_progress` system. While doing…
The changes introduced by https://github.com/odoo/odoo/commit/19d5367862528979abdcd411095f18d36bdbe7b8 aimed at aligning the mailing cron job logic with the new `_commit_progress` system.
While doing so, it accidentally added an if condition based on `self.env.get('ir_cron')`, which will always return False and never run the progress commit as intended.
To address this, in this PR:
- we change the condition to `if self.env.context.get('cron_id'):`, the cron_id context variable being set when the method was called from a scheduled action
- additionally we take the occassion to add an info log that outputs the computed send limit at the time the method was triggered. This will make it easier to investigate the logs ad-hoc in situations where the "Mail: Email Queue Manager" cron job fails silently because of a memory limit error. A high send limit (batch_size) increases the chances of memory errors proportionally. Knowing what the exact sending limit was at a given point in time makes investigation easier when trying to build a sequence of past events that could explain issues related to email sending.
OPW-6396087
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283402
Forward-Port-Of: odoo/odoo#282892Credit card and cash journal statement lists can now open individual statements in the form view. This fixes a dashboard workflow issue that prevented users from reviewing or editing statement details after opening the Statements list.
Original PR description
Issue: When opening the credit card statements list view from clicking the "Statements" button in the accounting dashboard of a credit card journal, the resulting list view does not allow clicking on any of the items to enter the form view Steps to reproduce: 1. Create a credit card journal and some credit card statements 2. Go to the accounting dashboard, and click on the button with three dots to the upper right of the credit card journal card and click "Statements" 3. Try to click on any of the statements in the list view and it won’t open any of them Cause: The window action for credit card journals (action_credit_statement_tree) was missing the form view in the view_mode Solution: Add form to the view_mode of action_credit_statement_tree. The cash journal bank statements window action (action_view_bank_statement_tree) was also missing the form view, so it was added as well opw-6449315 Forward-Port-Of: odoo/odoo#282816
This update removes unused invoice customization code for Gulf localization. It reduces maintenance complexity while keeping existing invoice behavior handled by the standard system.
Original PR description
Remove create() and _compute_narration() method overrides from l10n_gcc_invoice as they only existed to call _load_narration_translation(), which has already been disabled. The parent class implementations handle all required functionality. Keeps the codebase clean by removing unnecessary method overrides. Forward-Port-Of: odoo/odoo#281565 Forward-Port-Of: odoo/odoo#281395
Auto planning for sales-related planning work now correctly includes the last working day of a selected month. This prevents planned time from being cut short, helping teams schedule the full expected workload without manual corrections.
Original PR description
Steps to reproduce: --------------------------- 1. Install `sale_planning` with demo data. 2. Create a SO with a planning product, set the quantity to 100 hours, and confirm the SO. 3. Click the "To…
Steps to reproduce: --------------------------- 1. Install `sale_planning` with demo data. 2. Create a SO with a planning product, set the quantity to 100 hours, and confirm the SO. 3. Click the "To Plan" button, then click "Auto Plan". 4. Make sure the "Month" filter is selected in the scale options and observe the planned slots. Issue: -------- When auto planning slots for a month, the last day of the month is excluded. For example, slots are scheduled only until July 30th, even though July 31st is a working day. Cause: -------- While preparing the context, `stopDate` is set to July 31st at 00:00. It is then passed to [serializeDateTime()](https://github.com/odoo/odoo/blob/dacaad91bba8f959daf5d89a046c5a1c11e48eec/addons/web/static/src/core/l10n/dates.js#L553-L560), which converts the datetime to UTC. Depending on the user's timezone, this can shift the date to the previous day, causing the last day of the month to be excluded. Solution: ------------ Use `localEndOf()` to set `stopDate` to the local end of the selected range before passing it to `serializeDateTime()`. This ensures the last day of the month is preserved during UTC conversion. **NOTE:** Forward-port the solution from the 18.0 version, which was adapted to the publish shift use case in 18.3 and introduced this issue. Add a HOOT test case to prevent this regression in future versions. References: [18](https://github.com/odoo/enterprise/commit/bc3db24f83473d5646f7c2cfca8ed1c5b064ea2e) and [saas-18.3](https://github.com/odoo/enterprise/commit/c81fba31780869940f726b695ad46a87f69798fb) opw-6391495 Forward-Port-Of: odoo/enterprise#128775 Forward-Port-Of: odoo/enterprise#127950
Fixed an issue where planning shifts without a linked sales order line could cause an error when determining the customer. This makes shift handling more reliable and prevents interruptions for users working with sales planning.
Original PR description
Before this commit, when the shift has no SOL set, the `_compute_partner_id` crashes because the value for partner_id field is not set for that shift. This commit fixes the compute method of partner_id to make sure the value is correctly set for all shifts. Forward-Port-Of: odoo/enterprise#128965
A recent change that removed the default grouping option in Gantt views has been reverted. This restores expected grouping behavior in planning and related Gantt screens, helping users keep their usual view organization.
Original PR description
This reverts commit d35390a534fc60354a3c0174d6aa7cd158805f63 (#117918) task-6425644
Cancelling a payslip now correctly makes any related time off available to be recalculated in that payslip period. This prevents approved absences from being missed when payroll teams cancel and reset a payslip to draft.
Original PR description
How to reproduce: - Create a payslip for an employee and validate it - Create a new time off for said employee during the same period as the payslip and validate it - Go back to the payslip, cancel it and reset it to draft - The new time off is not included in the payslip Reason: When a payslip is cancelled, if there are time off during the same period as the payslip, their state is not reset to "to compute in next payslip" and instead stays in "to defer to next payslip", causing the issue How it was fixed: Now, when a payslip is cancelled, the new function "return_time_off_to_normal" will catch all leaves that are in the same time frame as the payslip to reset their state to "to compute in next payslip". Task ID: 6431576 Forward-Port-Of: odoo/enterprise#126868
Creating shortcuts for documents shared with a group now works correctly. The update also makes ownership access logging more reliable when group access is involved, reducing errors and improving consistency for shared document workflows.
Original PR description
Reproduce: try creating a shortcut for a document shared with a group. \+ increase robustness of logging owner access when creating a documents with an access command regarding a group. Task-6344800 Forward-Port-Of: odoo/enterprise#128926
Manual product replenishment now correctly shows a notification when it creates a purchase order. This helps inventory and purchasing users immediately see the result of ordering stock, while preserving existing purchase order line merging behavior.
Original PR description
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track…
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track Inventory` - Purchase > Add a Vendor `Ice cream man` - Reordering rules > Create a new reordering rule and save: - Trigger: Manual - Min: 5 - Max:10 - Press the `Order` button ## Observed Behavior: No notification is displayed about the newly created purchase order. ## Root cause: When the Order button is pressed, the `action_replenish` method is called. This method invokes `_procure_orderpoint_confirm` at [1]. The `_procure_orderpoint_confirm` function is responsible for creating procurements from orderpoints. During this process, it retrieves the procurement values using `_prepare_procurement_values` that are later used at [2]. However, `_prepare_procurement_values` only includes the orderpoint in the procurement values when the orderpoint's trigger is set to automatic, and not when it is manual, as shown at [3]. These procurement values are then used by `_run_buy` to create a purchase order and purchase order line at [4]. Since the orderpoint is not linked to the purchase order line in this case, no matching order is found at [5], which leads to the reported issue. **Which commit caused this unintentional behavior?** This behavior was unintentionally introduced by this [commit](https://github.com/odoo/odoo/commit/2a0d2c64d0027f540101447289b4c1a10cb3ecdf) . That commit fixed an issue where purchase order lines were not being merged for temporary manual orderpoints that are created dynamically based on product demand. [1]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L342-L349 [2]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L737-L741 [3]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L687-L701 [4]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock_rule.py#L156-L165 [5]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock.py#L276-L296 [6]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L365 [7]- https://github.com/odoo/odoo/blob/6a84d3e519892be333552e2e0ebf8da87e0a760c/addons/purchase_stock/models/purchase_order_line.py#L380-L384 ## Solution: Instead of removing the orderpoint ID from the procurement values, we reuse the same conditions used to identify temporary orderpoints for cleanup at [6]. Based on this, we determine how purchase order lines should be merged in the `_run_buy` method. With the previous implementation, no orderpoint was included in the procurement values. As a result, the condition at [7] checking for orderpoints always evaluated to True, causing the system to identify an existing purchase order line for the same product as a merge candidate. This solution allows us to retain that fix as well as avoid the error of notifications not showing up. opw-6311520 Forward-Port-Of: odoo/odoo#283853 Forward-Port-Of: odoo/odoo#271993
The mail compose process now uses the current progress-tracking method instead of an outdated one. This prevents unnecessary warning tracebacks in server logs during automated mail processing, helping keep operations monitoring cleaner without changing user-facing behavior.
Original PR description
Since 19.0 `_notify_progress`` is deprecated in favor of `_commit_progress``. See: https://github.com/odoo/odoo/commit/ee337934f9885834d95592946f435c6e1c8ef970 Currently, the mail compose wizard still calls an explicit _notify_progress followed by an explicit commit. This leads to warning tracebacks being dumped into the server logs (for example everytime the "Mail Marketing: Process queue" cron runs). We replace it with an equivalent `_commit_progress` call, which should log the progress and implicitly take care of the cursor commit. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282926
This fix prevents highlighted text from losing its background color when users turn paragraphs into lists or convert list items back to regular text. It also ensures clearing formatting removes background colors from list items as expected, making document editing more consistent.
Original PR description
Problem: Background color was lost both when converting text with a background color into a list item and when converting a list item with a background color back into a paragraph. Cause: - `insertListAfter` only copied `color` from the font wrapper to `li.style.color`, ignoring `background-color`. - Unwrapping a list item (`ListPlugin`) extracted `color`, `font-size`, and `text-align`, but ignored `backgroundColor`. Solution: - Preserve `background-color` from font wrapper onto `li.style.backgroundColor` when creating a list. - Restore `li.style.backgroundColor` onto a `<font>` wrapper when unwrapping a list item. Steps to reproduce: - Apply background color to a paragraph and toggle list -> background color is lost. - Apply background color to a list item and toggle list off -> background color is lost. opw-6481665 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283158
Point of Sale bills no longer show the self-service invoicing QR code while an order is still in draft. This prevents customers from invoicing or paying through the QR flow before the sale is finalized, avoiding inconsistent order and payment records.
Original PR description
Step to reproduce: - install point_of_sale - have a pos, with `Early Receipt Printing` and `Self-service invoicing` enabled - open a pos ,select a product - from action button, click on "Bill" Observation: - We can see QR code in bill, using which a person can invoice itself, even when order is in draft state. - This cause a lot of anomoly like payment line not visible in pos order, even after successful payment Cause: - Prior to this version, `Qr` related data is shown only when `order.finalized` i.e. `status = draft` . https://github.com/odoo/odoo/blob/6f64942cbbbf2355f7328394a6d484f6828a80f1/addons/point_of_sale/static/src/app/components/receipt/order_receipt.xml#L76 - After commit https://github.com/odoo/odoo/commit/aeaca097ae39b293bff47458ae8af019585f9224 we removed this condition Fix: - The condition is brought back. opw-6427152 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279382
This fixes an issue where temporary wizard screens could incorrectly appear as selectable records for marketing campaign references. The change keeps those reference lists cleaner and prevents users from choosing items that should not be used there.
Original PR description
Various places mistakenly used `model.is_transient()` to filter the transient models, where the model is `ir.model` record itself, which always returns False since `ir.model` is a regular persistent model. As a result, transient models (wizards) were never filtered out and allowed into the `utm_reference` Reference field selection. This commit fixes it by using `self.env[model.model].is_transient()` to call `is_transient` on the actual model. Task-6458883 Forward-Port-Of: odoo/odoo#283599 Forward-Port-Of: odoo/odoo#282711
This fixes a performance issue that could make Sign templates slow to open for users with limited template access. The system now loads related Sign template items in a single batch instead of repeating many separate lookups, improving responsiveness without changing user workflows.
Original PR description
Steps to reproduce: - with a user with "Sign / User: Own Templates" access rights - go to Sign / Templates - click on a template to open it => reading `sign.item.role.item_ids.template_id` triggers the computation of the related field `sign.item.template_id`, whose inverse `sign.template.sign_item_ids` carries a domain. When applying the domain, the sign.item's fields need to be fetched but they are fetched with one query per sign.item instead of a single batched one. task-6478942 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283864 Forward-Port-Of: odoo/odoo#282994
Closing the product configurator in Point of Sale no longer leaves optional products visible for an item that was not added. This prevents cashiers from seeing or selecting add-ons tied to a discarded product, reducing confusion during checkout.
Original PR description
When discarding the product configurator, we still showed the optional product. We no longer do that as no one wants to add optional products to a not-added product. task-6442422 Forward-Port-Of: odoo/odoo#283378 Forward-Port-Of: odoo/odoo#282916
The translation button now saves edits made inside related-record pop-up forms before opening the translation window. This ensures users see and translate the current text instead of outdated or empty content, while preserving existing behavior for editable lists.
Original PR description
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened…
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened in an x2many form dialog keeps its changes for itself until the dialog is saved, see https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/web/static/src/model/relational_model/static_list.js#L193. Its pending changes are not part of the root record changes, so saving the root sends nothing to the server, and the translation dialog then shows the stored terms instead of the current content, or no terms at all when the stored value is empty. The fix changes openTranslationDialog in translation_button.js, the place that decides which record to save. When the record keeps its changes for itself (record._noUpdateParent), the record is saved directly, like the button did before the commit above. The root record is still saved in the other cases, so the editable list case that commit fixed keeps working. Steps to reproduce: 1. Activate a second language in Settings > Translations > Languages 2. Open the Surveys app, open a survey and click a question in the Questions tab 3. In the Description tab, change the description 4. Click the EN button on the description field => the translation dialog shows the terms of the previous description, not the current one Ticket [link](https://www.odoo.com/odoo/project.task/6237291) opw-6237291 Forward-Port-Of: odoo/odoo#269507
This fix improves how product-related fields resize on screen by grouping browser layout work more efficiently. Large sales orders with many lines should load and respond much faster, reducing waiting time for users.
Original PR description
this is more like an experiment, to see if batching read and dom updates would help. this commit changes loading a SO view from 19.8s to 2.6s, so it looks like it helps 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#282788
The web search now ignores a default filter when its linked record no longer exists, instead of blocking the page with an error. This improves reliability for users opening saved actions or menus that reference outdated records.
Original PR description
…'t exist Have a search view with a m2o field Have an action that sets search_default_m2o: [/BAD ID/] Before this commit there was a crash After this commit, we simply ignore the filter. task-6469841 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#282738
This fixes an issue where pressing Shift+Enter in Safari created a new paragraph instead of a soft line break in the HTML editor. Users editing Knowledge articles on Mac Safari can now format text consistently with other browsers.
Original PR description
**Steps to reproduce:** - Use a Mac with Safari - Install Knowledge app - Go to any article - Press Shift+Enter to try to enter a soft line break - Hard split is done instead **Issue:** Shift+Enter causes a `insertParagraph` event instead of `insertLineBreak` in Safari, which triggers the `SplitPlugin` instead of the `LineBreakPlugin`. **Fix:** Check if the browser is Safari and call `insertLineBreak` from the `SplitPlugin` (when needed) by listening to the "keydown" events. (note: I was not able to find any other key combination to properly trigger the `insertLineBreak` event in Safari) opw-6413507 Forward-Port-Of: odoo/odoo#281458
Argentine delivery operations using class X document types no longer require CAI authorization code and expiration date fields. This aligns the workflow with government rules, which only require those details for class R delivery notes, reducing unnecessary blocking errors for users.
Original PR description
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to…
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to produce: - Install `l10n_ar_stock` with demo data - Switch Company to `(AR) Exento` - Create a warehouse - Configuration > Operation Types > Delivery Orders - Set Document Type to `'(94) MAILING X' `and try to save ## Observed Behavior: The fields 'CAI' and 'CAI Expiration Date', which represent the authorization code and expiration date issued by the government, are currently configured as required fields. **Expected Behavior:** As specified on the [government site](https://www.argentina.gob.ar/normativa/nacional/resoluci%C3%B3n-1415-2003-81316/actualizacion#:~:text=Los%20datos%20indicados%20en%20el%20inciso%20a%29%2C%20puntos%207%2C%2010%2C%2011%2C%2012%20y%2013%2C%20s%C3%B3lo%20ser%C3%A1n%20para%20los%20remitos%20clase%20%27R%27%2E): > > 12. Printing authorization code, preceded by the acronym 'CAI No. ...'. > 13. Expiration date of the receipt, preceded by the legend 'Expiration Date ...' > > 'The data indicated in section a), points 7, 10, 11, 12 and 13, will only be for 'R' class delivery notes.' These statements indicate that the information mentioned in points 12 and 13, including the **CAI** and **CAI Expiration Date** fields, is applicable only to **'R'** class delivery notes. Therefore, for class X delivery notes, these fields should be optional rather than required. ## Root Cause: According to [1], the field is configured as a required field when a Document Type ID is selected. This configuration causes the **CAI** and **CAI Expiration Date** fields to become mandatory, regardless of the document type requirements defined by the government specification. [1]- https://github.com/odoo/odoo/blob/62b05c4ea61942072b6b1fb420fe3efedb11ed14/addons/l10n_ar_stock/views/stock_picking_type_views.xml#L11-L16 ## Solution: Apply constraints that align with the government specifications, allowing the CAI and CAI Expiration Date fields to remain optional for document types where they are not required. opw-6359503 Forward-Port-Of: odoo/odoo#283288 Forward-Port-Of: odoo/odoo#275533
Fixes an issue in the HTML editor where selected link text using a gradient style could become invisible. Users can now clearly see and edit selected gradient-styled links, reducing confusion while creating or updating website content.
Original PR description
Problem: When text formatted with `.text-gradient` is inside a link with `.o_link_in_selection`, the selected text becomes invisible. `.text-gradient` sets `-webkit-text-fill-color: transparent`, which prevents `color: black !important` on `.o_link_in_selection` from taking effect. Cause: `-webkit-text-fill-color: transparent` from `.text-gradient` overrides standard text `color` rendering, causing the text to stay transparent against the selection highlight background. Solution: Set `-webkit-text-fill-color: black` on `.o_link_in_selection` to ensure text inside gradient links is rendered in black and remains clearly visible when selected. Steps to reproduce: - Add text "ABCD". - Apply gradient color to all text. - Create a link on "BC". - Place cursor/selection inside the new link. - Observe that the text is not visible. opw-6479350 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282952
This fixes a point of sale issue where the order details popup stayed on screen after choosing to edit a payment. Cashiers are now taken cleanly to the payment screen without an overlapping popup, reducing confusion during order corrections.
Original PR description
Steps to reproduce: ----------- - Validate an order, then open it from the ticket screen - Open the order details popup, click "Edit Payment" - Redirected to PaymentScreen, but the order details popup stays open on top of it Cause: --------- OrderDetailsDialog (opened via the dialog service) and PaymentScreen (opened via pos.navigate) are two separate stacks. Navigating to PaymentScreen does not close the dialog. Fix: -------------- Call dialog.closeAll() before pos.editPayment(order) in the editPayment callback passed to OrderDetailsDialog, so the dialog closes before navigating to PaymentScreen. task-6463084 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281960
This update corrects issues caused by a framework change so timers, active timesheet restoration, and the POS Urban Piper search bar behave reliably again. It prevents repeated timer resets and ensures users can resume active timesheets as expected.
Original PR description
OWL3's useEffect takes one argument, so the OWL2 deps callback is dropped: timer_start_field re-arms its interval on every render instead of on a timer_start it compares by value, and timesheet_systray never binds its `loaded` parameter, so it never restores the active timesheet. Came in with odoo/enterprise#128151 and odoo/enterprise#125368. Effects kept: they arm an interval and call into the timer service, not a derivation, so useOnChange restores both declared dependency lists verbatim. see https://odoo.github.io/owl/documentation/v3/owl/reference/hooks.html#useeffect community: https://github.com/odoo/odoo/pull/283883
The quick create fields in the bank reconciliation workflow were not displaying correctly after a recent interface framework update. This fix restores the expected full-width layout, making the form easier to use and reducing visual confusion for accounting users.
Original PR description
There was a change in the css since owl3, the quick create was impacted. By adding w-100 to the two fields, the problem is solved. no task id
Documents created by splitting a multi-page PDF now appear in a predictable order instead of being randomly arranged. This makes it easier for users to review and manage split pages in the Documents kanban view.
Original PR description
steps: - upload a multi-page pdf - split all the pages -> they now show in a random order The issue is that the current documents are sorted by create_date desc, but the split creates all the different documents at the same time so they are sorted in the order they happen to be on the disk. We now add a sort by id to act as a tie-breaker. opw-6176840 Forward-Port-Of: odoo/enterprise#128410 Forward-Port-Of: odoo/enterprise#117255
Euro payments sent through non-euro bank journals can now be configured to use the correct SEPA payment indicators in generated ISO20022 files. This helps avoid bank rejection or processing issues while leaving existing behavior unchanged unless the new option is enabled.
Original PR description
Steps to reproduce: - Configure a bank journal whose currency isn't EUR (e.g. SEK, USD, GBP). - Use the generic ISO20022 payment method to send a payment in EUR to a SEPA-zone IBAN. - Generate the…
Steps to reproduce: - Configure a bank journal whose currency isn't EUR (e.g. SEK, USD, GBP). - Use the generic ISO20022 payment method to send a payment in EUR to a SEPA-zone IBAN. - Generate the pain.001 file: SvcLvl/Cd is NURG and ChrgBr is SHAR instead of the SEPA-mandated SEPA/SLEV. Cause of the issue: SvcLvl/Cd and ChrgBr are derived purely from the technical payment method code, not from whether the transaction actually qualifies as SEPA. The 'sepa_ct' payment method (which hardcodes SvcLvl=SEPA and ChrgBr=SLEV) is only ever offered on journals whose own currency is EUR. A journal in any other currency that occasionally sends a EUR payment therefore always falls back to the generic 'iso20022' payment method, which unconditionally reports NURG/SHAR. The same gap already exists, and is already solved, for Switzerland via the 'iso20022_ch_force_sepa' parameter, which dynamically remaps 'iso20022_ch' batches to 'sepa_ct' when their currency is EUR. No equivalent existed for any other country. Solution: Generalize that mechanism with a new opt-in parameter, 'account_iso20022.force_sepa_for_eur'. When set, a EUR-denominated batch generated through the generic 'iso20022' payment method is remapped to 'sepa_ct' for XML-generation purposes, so it correctly reports SvcLvl=SEPA and ChrgBr=SLEV. The parameter defaults to disabled, so the default behavior is unaffected unless explicitly turned on. opw-6006230
The barcode delivery flow now uses the real storage location of a scanned serial item instead of falling back to the parent warehouse location. This prevents incorrect stock deductions, stale inventory records in sublocations, and negative stock in parent locations when processing deliveries.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial…
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial stored in a sublocation (e.g. WH/Stock/Section 2). 4. Confirm a sale order for it, open the delivery in Barcode, and scan an unreserved serial. Issue --- Scanning the unreserved serial creates a new move line that falls back to _defaultLocation() because the decoded scan carries no source location (the operation type does not require scanning one) and never carries the serial's quant location. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_model.js#L937-L944 For a delivery, that default resolves to the picking's own source location (the parent WH/Stock), so the line is sourced from the parent instead of the sublocation where the serial physically sits. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_picking_model.js#L1542-L1544 On validation the unit is deducted from the parent location instead of the sublocation, leaving a stale quant of the serial in the sublocation and a negative quant at the parent. opw-5864414 Forward-Port-Of: odoo/enterprise#128523 Forward-Port-Of: odoo/enterprise#121375
Colombian electronic invoicing users can now generate invoice PDFs for vendor bills after completing the reception and acceptance flow. The fix correctly reads wrapped invoice attachments, preventing a server error that blocked PDF creation.
Original PR description
**Steps to reproduce:** * Install the **l10n_co_edi** module. * Go to **Settings** and, under **Colombian Electronic Invoicing**: * Disable **Testing Mode**. * Enable **DIAN Demo**. * Create a vendor…
**Steps to reproduce:**
* Install the **l10n_co_edi** module.
* Go to **Settings** and, under **Colombian Electronic Invoicing**:
* Disable **Testing Mode**.
* Enable **DIAN Demo**.
* Create a vendor bill with a tax and confirm it.
* Click **Acknowledge Reception**.
* Click **Receive Goods**.
* Click **Accept**.
* From the gear menu, click **Print → Invoice PDF**.
**Observed behavior:**
* A server error is raised:
```
lxml.etree.XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1
```
* The PDF cannot be generated.
**Cause (two-step):**
1. **ZIP not unwrapped:** The original code called `etree.fromstring(self.l10n_co_edi_attachment_id.raw)` directly for all move types. For vendor bills (`in_invoice`) the attachment is stored as a ZIP file, so `raw` is compressed binary data — not XML. Passing it to `etree.fromstring` directly produces the `XMLSyntaxError` above.
2. **AttachedDocument wrapper not unwrapped:** Once the ZIP is correctly decompressed with `xml_utils._unzip`, the resulting XML is an `AttachedDocument` wrapper, not a plain `Invoice`. The actual invoice XML is embedded as CDATA inside `cac:Attachment/cac:ExternalReference/cbc:Description`. `_get_qr_code_value` expects the inner document and searches for nodes like `cac:AccountingSupplierParty`, `cac:LegalMonetaryTotal`, and `sts:QRCode` — none of which exist on the outer wrapper, so the QR code was blank or the method crashed.
**Fix:**
* In `_l10n_co_edi_get_invoice_report_qr_code_value`, for vendor bills (`in_invoice`/`in_refund` without support document), unzip the attachment and immediately attempt to extract the inner invoice XML from `cbc:Description` using `findtext('.//{*}Description')` (lxml namespace wildcard). If the node is present, parse its text as the actual document; otherwise fall back to the unzipped bytes directly.
**Note:**
* A unit test for the `AttachedDocument` unwrapping path was not added because the test would require a zipped fixture file (the vendor bill attachment is stored as a ZIP) which is not appropriate to commit.
* A regression test was added in `test_accept_by_customer`: after the full commercial event flow the method is called inside a `try/except etree.XMLSyntaxError` block so that any XML parse failure surfaces as a proper test *failure* rather than an unhandled test *error*.
opw-6417422
Forward-Port-Of: odoo/enterprise#128694
Forward-Port-Of: odoo/enterprise#126463Fixes an error that occurred when users clicked the "Recorded" button on field service interventions in setups without Project planning integration. The button now reliably shows the timesheets logged for the intervention, improving visibility into recorded work and billing details.
Original PR description
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field…
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field service billing feature (Planning > Configuration > Settings > Field Service > "Invoice your time and materials to your customers") without installing Project's planning integration 2. Set the project in Planning > Configuration > Settings > Field Service 3. Create an intervention and assign a resource to it 4. Click the "Recorded" smart button **Current behavior:** 'super' object has no attribute 'action_open_timesheets' **Expected behavior:** The timesheets logged on the intervention are listed. **Cause of the issue:** `action_open_timesheets` on `planning.slot` is defined in two modules only: `project_timesheet_forecast` provides the base implementation, and `planning_field_service_sale_timesheet` extends it through `super()`. Since `59a04091c403` dropped `project_timesheet_forecast_sale` from the dependencies of `planning_field_service_sale_timesheet`, nothing guarantees the base implementation is part of the model's inheritance chain anymore: `project_timesheet_forecast` is auto installed only together with `project_forecast`, which no module of the field service stack depends on. The smart button is rendered by `planning_field_service_sale_timesheet` itself, so it stays visible in such an installation while the `super()` call has nothing to resolve to. **Fix:** That same commit already made the field service module self-sufficient for `_get_timesheetable_project`, `_compute_allow_timesheets` and `_compute_allow_billable`, leaving the project forecast flavour to the `project_timesheet_forecast_field_service_sale` bridge, and `action_open_timesheets` is the only method that was left relying on the other stack. Building the action from the module's own hooks preserves that separation, whereas depending on `project_timesheet_forecast` again would pull Project back into every field service installation, which is precisely what that commit set out to avoid. opw-6391972
The project Sales button now shows all sales linked to a project, including rental orders, so the list matches the total shown on the button. This prevents users from missing rental-related revenue or order details when reviewing project sales.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Observe the "Sales" stat button counts 2 Sales. 4. Click the stat button. Only the standard Sales Order is displayed. Issue --- In saas-18.4, the project Sales stat button calls action_view_sos without the from_embedded_action context key. As a result, _get_sale_orders_domain applies the non-rental filter by default, causing rental orders to be excluded from the action even though they are included in the displayed counter. Expected Behavior --- The Sales stat button should display all orders linked to the project, including both standard and rental orders, matching its total counter. Fix --- Return the base project domain unmodified when from_embedded_action is not set in the context. task-6140201 Forward-Port-Of: odoo/enterprise#128468 Forward-Port-Of: odoo/enterprise#121449
The LinkedIn social account refresh now handles cases where LinkedIn returns no statistics for an account. This prevents an unexpected crash and keeps social media data refreshes running reliably.
Original PR description
Bug === When the LinkedIn API returns no statistics for the account, the refresh crashes. Task-6425391 Forward-Port-Of: odoo/enterprise#126326
Annual report articles can now be exported to PDF reliably in newer trial environments. This prevents users from hitting an export error caused by an outdated PDF library reference, ensuring reports remain downloadable as expected.
Original PR description
When exporting an article to PDF, `export_article_to_pdf` uses `PdfReader.outlines` to retrieve the PDF bookmarks at [1]. This causes the following error on Trial DBs: `AttributeError: 'PdfReader' object has no attribute 'outlines'` The `outlines` property has been deprecated in PyPDF2 in favor of `outline` PyPDF2 doc [ref](https://pypdf2.readthedocs.io/en/3.x/modules/PdfReader.html?utm_source=chatgpt.com#PyPDF2.PdfReader.outlines). The issue is reproducible on Trial DBs running **Ubuntu 26.04** with **Python 3.14**, while older environments only raise a deprecation warning. Solution: Replace `PdfReader.outlines` with `PdfReader.outline` to use the supported API and prevent the PDF export from failing with an `AttributeError`. [1]: https://github.com/odoo/enterprise/blob/912a47b8f0828ef8316b7e4ecdabf8a2f305b313/accountant_knowledge/controller/main.py#L462 opw-6418289
This fix prevents errors in Sales Planning reports when planning slots are grouped by customer. The system now uses the correct customer reference depending on the installed features, keeping reporting stable across configurations.
Original PR description
Before this commit, #122034 converted the related non-stored `partner_id` field in `planning.slot` into a compute non-stored field with a search method, the problem is that field was used as groupby inside a read_group which causes a traceback since the field is no longer reachable in SQL. This commit alters the groupby in problematic _read_group methods to use partner_id field when it is stored (when field service is installed) otherwise the groupby should be `sale_order_id.partner_id`. Forward-Port-Of: odoo/enterprise#128540
Opening the timesheet systray from a task no longer clears an already running timer. This prevents users from losing tracked time when the form is automatically prefilled with the related project and task.
Original PR description
Before this commit, the prefill used when the user opens the timesheet systray when his current loaded page is a task, will alter the form view in the timesheet systray to set the project and task when those fields are unset. The problem is `unit_amount` is also given to 0 and so the timer is reset due to the prefill system. This commit makes sure the `unit_amount` field is not inside the prefill data to make sure the timer is no longer reset. opw-6481443 Forward-Port-Of: odoo/enterprise#128672 Forward-Port-Of: odoo/enterprise#128531
The pull request records that GitHub user kshitij-nariya has signed Odoo's Individual Contributor License Agreement. This administrative update helps ensure their future contributions can be reviewed and merged without CLA-related blockers.
Original PR description
Description of the issue/feature this PR addresses: Signed the Odoo Individual Contributor License Agreement to contribute to the Odoo repository. Current behaviour before PR: The CLA signature is missing for GitHub user `kshitij-nariya`, which will prevent future contributions from being accepted and merged. Desired behaviour after PR is merged: The CLA signature for `kshitij-nariya` is recorded in the repository, allowing future pull requests and contributions to be successfully merged. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282808