Tuesday, July 21, 2026
9 changes · saas-19.1
Resolved issues and error corrections
This fix makes the point-of-sale barcode lookup check product creation permissions immediately and consistently. It helps avoid inconsistent behavior when staff try to create products from barcode lookup screens.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#124825 Forward-Port-Of: odoo/enterprise#123073
Steps to reproduce: - Install the PayU payment provider. - Click the Connect button and complete the onboarding flow. - After being redirected back to the PayU provider form, click Disconnect. Issue: - After confirming the disconnection, a validation error is raised stating that the PayU fields must be filled in. Cause: - During disconnection, the PayU-specific fields are cleared. At that point, `_check_required_if_provider` is triggered, and since those fields have the `required_if_p
Original PR description
Steps to reproduce: - Install the PayU payment provider. - Click the Connect button and complete the onboarding flow. - After being redirected back to the PayU provider form, click Disconnect. Issue: - After confirming the disconnection, a validation error is raised stating that the PayU fields must be filled in. Cause: - During disconnection, the PayU-specific fields are cleared. At that point, `_check_required_if_provider` is triggered, and since those fields have the `required_if_provider` attribute, it raises a `ValidationError` because their values are now `None`. Fix: - Remove the `required_if_provider` attribute from the PayU-specific fields. opw-6391133 Forward-Port-Of: odoo/odoo#276567
Steps to reproduce: 1. Edit/Create an activity type (e.g., "To Do") and enable "Keep Done". 2. Schedule an activity of this type on a journal (or a journal entry/move) with a deadline in the past. 3. Mark the activity as done. 4. Go to the Accounting Dashboard. Notice that the activity is still shown as "overdue" in red on the journal card. When an activity type has "Keep Done" enabled, completed activities are not deleted from the database. Instead, they are archived by setting `active =
Original PR description
Steps to reproduce: 1. Edit/Create an activity type (e.g., "To Do") and enable "Keep Done". 2. Schedule an activity of this type on a journal (or a journal entry/move) with a deadline in the past. 3. Mark the activity as done. 4. Go to the Accounting Dashboard. Notice that the activity is still shown as "overdue" in red on the journal card. When an activity type has "Keep Done" enabled, completed activities are not deleted from the database. Instead, they are archived by setting `active = False` and `date_done` is populated. Since the activity dashboard query retrieves records via direct SQL, it bypasses Odoo's automatic active filtering on `mail.activity`. As a result, archived (done) activities were incorrectly fetched and displayed on the journal dashboard cards, appearing as overdue. This commit resolves the issue by explicitly adding `AND activity.active = TRUE` to the SQL queries. Task-6142042 Forward-Port-Of: odoo/odoo#276998 Forward-Port-Of: odoo/odoo#274313
The reversal wizard always injected a shared 'R4' onto every credit note it created, so a credit note of a simplified invoice never got the required 'R5', and reversing several invoices of mixed simplified status at once forced the same reason onto all of them. The wizard now derives the reason per original move ('R5' if it is simplified, 'R4' otherwise) instead of using one shared value, while still respecting an explicit manual choice. `l10n_es_is_simplified` already freezes correctly
Original PR description
The reversal wizard always injected a shared 'R4' onto every credit
note it created, so a credit note of a simplified invoice never got
the required 'R5', and reversing several invoices of mixed simplified
status at once forced the same reason onto all of them.
The wizard now derives the reason per original move ('R5' if it is
simplified, 'R4' otherwise) instead of using one shared value, while
still respecting an explicit manual choice. `l10n_es_is_simplified`
already freezes correctly on the credit note via its existing compute,
so no new compute is needed on `l10n_es_edi_verifactu_refund_reason`.
task-6358684
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#276187PR #247474 fixed an error where the lock date restriction was applied overzealously, restricting `stock.picking` models with a `scheduled_date` field before the lock date. This field does not affect accounting entries. The previous fix was to only check the `scheduled_date` field if the picking was in the `done` state. A more complete fix is to simply not check the `scheduled_date` field. opw-6311703 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-
Original PR description
PR #247474 fixed an error where the lock date restriction was applied overzealously, restricting `stock.picking` models with a `scheduled_date` field before the lock date. This field does not affect accounting entries. The previous fix was to only check the `scheduled_date` field if the picking was in the `done` state. A more complete fix is to simply not check the `scheduled_date` field. opw-6311703 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270875
Issue: In a multi-company environment, when an attachment is uploaded in the chatter, the resulting `ir.attachment` record incorrectly sets the company_id to the current user's default company. This occurs regardless of the active company or the company associated with the record the attachment is linked to. Steps to reproduce: In a multi-company setup, activate only Company B. Open any chatter and attach a file. Navigate to Settings > Technical > Data Structure > Attachments. Current b
Original PR description
Issue: In a multi-company environment, when an attachment is uploaded in the chatter, the resulting `ir.attachment` record incorrectly sets the company_id to the current user's default company. This…
Issue: In a multi-company environment, when an attachment is uploaded in the chatter, the resulting `ir.attachment` record incorrectly sets the company_id to the current user's default company. This occurs regardless of the active company or the company associated with the record the attachment is linked to. Steps to reproduce: In a multi-company setup, activate only Company B. Open any chatter and attach a file. Navigate to Settings > Technical > Data Structure > Attachments. Current behaviour: The created attachment has its company_id set to the user's default company, rather than the currently active company, or the company of the record, even when the record has a company_id field. This behavior introduces inconsistencies in data visibility, particularly when attachments appear to belong to a company different from the one associated with the related business record. Behaviour After Fix: If the related record (i.e., the model the attachment is linked to) contains a company_id field, its value will be used as the attachment's company_id otherwise, the attachment's company_id will be set to the currently active company's id. This logic ensures proper alignment between attachments and their related business records and also maintaining consistency in multi-company scenarios. task-4563173 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277582 Forward-Port-Of: odoo/odoo#235665
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynch
Original PR description
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynchronous permission check with a getter that evaluates product creation rights. - Cache the group access information in `posService` and let the hr override use the getter. Task-6361787 Related PR: https://github.com/odoo/enterprise/pull/123073 Forward-Port-Of: odoo/odoo#277216 Forward-Port-Of: odoo/odoo#274420
Issue: When a shopper pays for an online order entirely using a reward (e.g. a discount code covering 100% of the total), the order total is zero. With automatic invoicing enabled, an invoice with an amount of 0 is created. But, the 0 invoice is never emailed to the customer. Whereas, for orders where the total is more than 0, an invoice is created, then emailed to the customer. The customer should be emailed the invoice, even if its amount is 0. Steps to reproduce: 1. Enable automatic invo
Original PR description
Issue: When a shopper pays for an online order entirely using a reward (e.g. a discount code covering 100% of the total), the order total is zero. With automatic invoicing enabled, an invoice with an…
Issue: When a shopper pays for an online order entirely using a reward (e.g. a discount code covering 100% of the total), the order total is zero. With automatic invoicing enabled, an invoice with an amount of 0 is created. But, the 0 invoice is never emailed to the customer. Whereas, for orders where the total is more than 0, an invoice is created, then emailed to the customer. The customer should be emailed the invoice, even if its amount is 0. Steps to reproduce: 1. Enable automatic invoicing. 2. Create a code for a 100% discount. 3. As a shopper, add a product to cart on the website. 4. While checking out, apply the 100% discount code to the order. 5. Complete the checkout. 6. Confirm that an invoice was created and posted, but was not emailed to the customer. Explanation: Normally, order confirmation and invoicing are handled by the `_post_process` method on the `payment.transaction` model. With automatic invoicing enabled, `_post_process` confirms the sale order, creates the invoice, and sends the invoice via `_send_invoice` (another method on the `payment.transaction` model). If `sale.async_emails` is enabled, `_post_process` will trigger a cron that invokes `_send_invoice` instead of invoking it directly. When an order is fully covered by a reward, there's nothing to pay. In this case, no payment.transaction record is ever created, and `_post_process` never runs. Instead, the order is confirmed through the `_validate_order` method on the `sale.order` model. The `sale_loyalty` module extends `_validate_order` so that, with automatic invoicing enabled, it will create and post an invoice for zero-amount orders. But, nothing in this path ever calls `_send_invoice` or an equivalent. So, the invoice is created and posted but never sent. Solution: This adds logic for sending invoices to the extension of `_validate_order` in the `sale_loyalty` module. We mirror the logic used in `_send_invoice` in the `payment.transaction` model. Notes: There is duplicated code from `_send_invoice` in this fix. That is because `_send_invoice`, a method on the `payment.transaction` model, can't be used in this flow. A fix that avoids code duplication would require serious refactoring. This will never trigger a cron to send the invoice, even if `sale.async_emails` is enabled. That is because the cron invokes `_send_invoice`. Since fully reward-covered orders are probably not common, any performance benefits of using a cron are probably not significant. But, making a new cron to be used in this case is also an option. opw-6363334 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275190
Miscellaneous changes
_**Description of the issue/feature this PR addresses:**_ SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines(). That method filters the whole order_line recordset on every call. Since the onchange is triggered by any change to order_line, this noticeably slows down every modification of the lines on large orders even when the order contains no combo product at all. _**Current behavior before PR:**_ For every order line,
Original PR description
_**Description of the issue/feature this PR addresses:**_ SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines(). That method…
_**Description of the issue/feature this PR addresses:**_
SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines().
That method filters the whole order_line recordset on every call.
Since the onchange is triggered by any change to order_line, this noticeably slows down every modification of the lines on large orders even when the order contains no combo product at all.
_**Current behavior before PR:**_
For every order line, _onchange_order_line calls line._get_linked_lines(), and each call re-scans the entire order_line recordset with filtered(). The cost therefore grows with the total number of lines (regular lines included), so editing any line on a large order is sluggish.
_**Desired behavior after PR is merged:**_
The {line: linked_lines} mapping is computed in a single pass via the new method SaleOrderLine._get_linked_lines_by_line(), called once per onchange instead of once per line.
The method _get_linked_lines() is kept as a thin single-record wrapper delegating to the batched method, preserving backward compatibility for external callers. Behavior is unchanged and only the performance is improved: the onchange now scales linearly with the number of order lines.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277185