Tuesday, March 17, 2026
13 changes · saas-18.4
Resolved issues and error corrections
Fixed an issue that could block lunch orders when a vendor had an availability end date set. Employees can now place lunch orders normally for eligible vendors, reducing ordering disruptions.
Original PR description
Steps to reproduce: ------------------------------ 1. Install Lunch module 2. Lunch > configurations > Vendors 3. Open any vendor and set Until date to any near future date 4. Go to My Lunch > New Order 5. Click on Any product with above vendor > Add to Cart 6. Click on Order Now Observation: ------------------------------ Traceback Occurs: ``` return not (self.recurrency_end_date and date.date() >= self.recurrency_end_date) and self[fieldname] ^^^^^^^^^ AttributeError: 'datetime.date' object has no attribute 'date' ``` Issue: ------------------------------ `_available_on_date` calls `date.date()` unconditionally, which fails when passed a `datetime.date` object (from `lunch.order`) since date objects lack the `date()` method. Solution: ------------------------------ Check instance type before calling `date()` to handle both `datetime.datetime` and `datetime.date` objects correctly. opw-5948688 Forward-Port-Of: odoo/odoo#249449
This fix prevents point of sale combo item prices from being reset when staff change a lot or serial number on a tracked product. It helps ensure customers are charged the intended combo price and reduces manual corrections at checkout.
Original PR description
Step to reproduce: - have a lot tracked product, product 1 (price = 10) - create a combo product with product 1, with price (100) - start a pos, add combo product in order, - notice total price is 100 - change lot number of product 1, - notice order price reset to 10. Cause: - When the lot number is changed, `set_quantity_by_lot` is triggered. - This calls `set_quantity`, which resets the price and loses the combo pricing. Fix: - use `keep_price` = true parameter when calling `set_quantity` if orderline has combo_parent_id opw-5495409 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253947 Forward-Port-Of: odoo/odoo#246252
This fix prevents users from copying content from publicly shared read-only spreadsheets. It helps protect shared spreadsheet data from unintended reuse while preserving public viewing access.
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 Forward-Port-Of: odoo/odoo#254094
Users can now cancel large image uploads from the media dialog without seeing an error or leaving the page in a broken state. The upload is properly stopped when Discard is clicked, preventing unwanted files from being uploaded afterward.
Original PR description
Steps to Reproduce: 1. Open the website module. 2. Open the media upload dialog to upload an image by either double-clicking the logo or replacing the existing image. 3. Upload a large file. 4. Abort…
Steps to Reproduce: 1. Open the website module. 2. Open the media upload dialog to upload an image by either double-clicking the logo or replacing the existing image. 3. Upload a large file. 4. Abort the upload before it finishes by clicking the 'Discard' button in the media dialog box. After performing these steps, a traceback is observed. Before this commit: - Image upload failures would throw uncaught exceptions. - These exceptions would interrupt the flow and result in a poor user experience with no clear feedback. - Even after clicking the discard button the image was still getting uploaded. After this commit: - Uploads can be safely aborted when the media dialog is discarded. - Ongoing XHR requests and RPC calls are properly cancelled. - The upload loop stops immediately when an abort is triggered with no traceback. - Users get a predictable and clean exit instead of a broken state. - Files are no longer uploaded after clicking Discard. ### task-4752497 Forward-Port-Of: odoo/odoo#249245 Forward-Port-Of: odoo/odoo#219081
Event tickets sold through Point of Sale now participate in price recalculation. This means POS uses the event ticket price when no pricelist applies, but correctly applies available pricelist rules when relevant, helping ensure customers are charged the intended price.
Original PR description
Event tickets in POS would have their price locked to the price defined in the event itself. They would be filtered out of any price recalculation inside the POS to keep the POS from recalculating the price based on the `product_template` and to keep the price defined in the event itself. This PR will add event tickets back into price recalculation. It will set the price to the price defined inside the event if no pricelist is applicable, or use the pricelist to calculate the price if there is one applicable. Task-[5092613](https://www.odoo.com/odoo/project/1737/tasks/5092613) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248454
Portal users can now submit website forms that create project tasks without hitting an error on the confirmation page. This prevents a failed post-submission experience and keeps the task creation flow working as expected.
Original PR description
Currently, submitting a website form that creates a task crash for portal users on the confirmation page. ### **Steps to reproduce:** 1) Install website_project with demo data 2) Create a website…
Currently, submitting a website form that creates a task crash for portal users on the confirmation page. ### **Steps to reproduce:** 1) Install website_project with demo data 2) Create a website form that creates a task 3) Set a project on the form 4) Submit the form as a portal user ### **Error:** `AccessError: You do not have enough rights to access the field project_privacy_visibility on Task (project.task)` ### **Root Cause:** The confirmation template evaluates `task.project_privacy_visibility` in a t-if condition at [1]. since [commit](https://github.com/odoo/odoo/pull/203891/changes/17664b3f118491f954dd6a810521ce5865d51a43), project task restricts portal users to a whitelist of fields defined by [_portal_accessible_fields()](https://github.com/odoo/odoo/blob/b9e3ca44ceb2b0b35b5e91a06f2905e042aa7f89/addons/project/models/project_task.py#L1015-L1019). Field access is then validated in [_has_field_access()](https://github.com/odoo/odoo/blob/b9e3ca44ceb2b0b35b5e91a06f2905e042aa7f89/addons/project/models/project_task.py#L1021-L1031), which denies read access to fields not present in this whitelist. `project_privacy_visibility` is not part of the portal readable fields list. When the template tries to read it, _has_field_access() rejects the operation and raises an AccessError. [1]- https://github.com/odoo/odoo/blob/b9e3ca44ceb2b0b35b5e91a06f2905e042aa7f89/addons/website_project/views/project_portal_project_task_template.xml#L13-L16 ### **Fix:** Use `sudo()` when reading `project_privacy_visibility` in the template to avoid the portal field access restriction. **opw-6010622** Forward-Port-Of: odoo/odoo#254099
This fix restores the copy button in spreadsheets after a recent change accidentally disabled it. Users can once again copy spreadsheet content normally, reducing disruption in day-to-day work.
Original PR description
Fix error which disabled the copy button. 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#252977
Sales users who can access a quote can now print it even when products include Intrastat commodity codes. This prevents unnecessary access errors and avoids requiring accounting permissions just to generate customer quotations.
Original PR description
**Steps to reproduce:** - Install Accounting, Sales and account_intrastat - Create a user with Sales rights only - Create a product with an Intrastat Commodity Code - Connect with the created user - Create a SO with the Intrastat product - Print PDF Quote **Issue:** An access error is raised while trying to access "account.intrastat.code" field. The user needs to have an Accounting group in order to access this field. **Cause:** When printing the quote, the SO is exported in a XML to be embedded in the PDF. The field is accessed at that moment. opw-5976725 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where multiple email addresses associated with a contact were being overwritten when creating a helpdesk ticket. The change ensures that all email addresses linked to a contact are correctly captured, improving the reliability of ticket creation. This addresses a potential data loss scenario.
Original PR description
Prerequisites: ------------------------------ 1. Set up incoming mail server with Create a New Record set to Helpdesk Ticket 2. From Settings, create one Alias Domain Steps to reproduce:…
Prerequisites: ------------------------------ 1. Set up incoming mail server with Create a New Record set to Helpdesk Ticket 2. From Settings, create one Alias Domain Steps to reproduce: ------------------------------ 1. Install Helpdesk module 2. Open Helpdesk Team > Settings 3. Inside Channels, Set the mail used for the incoming server and the alias created 4. Set Accept Emails From to Everyone 5. Create a new contact with multiple emails (eg: `a@b.com`, `c@d.com`) 6. From Fiest mail (eg: `a@b.com`), Send one mail to mail set in the helpdesk team alias mail. 7. Open Incoming mail sever > Click on Fetch Now 8. Open Created Contact Observation: ------------------------------ The contact's email field is overwritten. The second email address (e.g. `c@d.com`) is lost Issue: ------------------------------ After `create`, since `partner_email` was stored with a value that differs from `partner_id.email`, the inverse method `_inverse_partner_email` kicks in. This is where `_get_partner_email_update()` is called. In `_get_partner_email_update()` `tools.email_normalize()` only handles a single email. When the partner has multiple email, the normalization keeps both, while the ticket email normalizes to just have one mail. The strict `!=` comparison fails, triggering the unwanted update. https://github.com/odoo/enterprise/blob/7c23efafe368787c858db31cec075f642ae6715b/helpdesk/models/helpdesk_ticket.py#L363-L369 Solution: ------------------------------ Instead of comparing the full normalized strings, we should check whether the ticket's normalized email is contained within the set of the partner's normalized emails Note for reviewer ----------------------------- After discussion with the PO (LNA), his opinion is that having multiple email addresses in a single field is not a good practice. This use case is only semi-supported in Odoo, it may work in some cases, but it is not reliable. The recommended approach is to create separate contacts for each email address. That said, we should also avoid automatically clearing or altering the existing value in the field. Based on this, I have implemented a minimal fix that prevents altering the existing value in the field. I am leaving it up to the review to decide whether this fix is worth keeping from a technical standpoint. opw-5478067 Forward-Port-Of: odoo/enterprise#107808
This update resolves an issue where payrun creation failed for employees with contracts starting mid-period. The fix ensures accurate calculation of integration factors by handling contract start dates correctly, preventing an error related to accessing the year of the start date. This ensures all employees are paid accurately.
Original PR description
An error is thrown when an employee's contract starts mid-period. ```py Invalid Operation Wrong python code defined for: - Employee: Cesar Osbaldo Cruz Solorzano - Version: False - Payslip: Payslip -…
An error is thrown when an employee's contract starts mid-period.
```py
Invalid Operation
Wrong python code defined for:
- Employee: Cesar Osbaldo Cruz Solorzano
- Version: False
- Payslip: Payslip - Cesar Osbaldo Cruz Solorzano - 01/16/2026 - 01/31/2026
- Salary rule: Integrated Daily Wage (Base) (INT_DAY_WAGE_BASE)
- Error: AttributeError("'bool' object has no attribute 'year'") while evaluating
'\nresult = round(payslip.l10n_mx_integration_factor * payslip.l10n_mx_daily_salary, 4)\n
```
Steps to reproduce:
1. Install `l10n_mx_hr_payroll` modules
2. Switch to ESCUELA KEMPER URGATE company
3. Go to Employees and open Cesar Osbaldo Cruz Solorzano
4. Go to Payroll tab, change the start date of contract to 01/10/2026 and save
5. Go to Payroll > Payslips > Payslips and create a new pay run
6. Select Salary Structure 'Mexico: Regular Pay', Pay Schedule 'Monthly' and Period '01/01/2026 -> 01/31/2026'
7. Click on Continue, select Cesar and click on Select
8. An error is thrown
Problem:
In `_compute_integration_factor` method, `_get_first_contract_date` is called with context `before_date`, it returns `False` as the contract starts after the payslip period. This causes an error when trying to access the `year` field of `start_date`.
Solution:
Add a fallback to call `_get_first_contract_date` without context in case the first call returns `False`.
target: saas-18.4
task-6034836This update ensures that NACHA payment files use the correct bank account holder's name instead of the customer's name in Odoo. Prioritizing the accurate account holder name improves payment processing accuracy and reduces potential errors with financial institutions. This change ensures compliance and avoids issues with bank reconciliation.
Original PR description
The NACHA entry detail was using the partner's name (res.partner.name) for the Individual Name field. This should instead prioritize the Account Holder Name (acc_holder_name) from the bank account, as this reflects the actual name on the bank account which may differ from the partner's name in Odoo. The code now uses bank.acc_holder_name if set, and falls back to payment.partner_id.name if not set. Forward-Port-Of: odoo/enterprise#108414 Forward-Port-Of: odoo/enterprise#105582
This update resolves an issue where night shift slots (e.g., 20PM - 4AM) weren't visible in the weekly planning view. The fix adjusts how the system displays multi-day slots, ensuring all scheduled hours are accurately shown. This improves the planning experience for employees with flexible work arrangements.
Original PR description
**Steps to reproduce** 1. Have an employee using a flexible schedule 2. Create a slot from e.g. 20PM to 4AM for this employee. Make sure this is the only slot that week for the employee. 3. Publish…
**Steps to reproduce** 1. Have an employee using a flexible schedule 2. Create a slot from e.g. 20PM to 4AM for this employee. Make sure this is the only slot that week for the employee. 3. Publish the Schedule and send it to the employee. Open the outgoing mail to access the link to the planning view. Issue: the slot is not visible in the week view. **Cause** https://github.com/odoo/enterprise/blob/04a885dbb6eed96297cb5ce9a155ebf8e169427c/planning/controllers/main.py#L193-L194 The `event_hour_min` and `event_hour_max` returned by `planning_get` and used to control the min/max hours displayed in the week view, didn't account for slots over multiple days. For a slot between 20pm and 4am, the `event_hour_max` should be the end of the day, and the `event_hour_min` should be the start of the day. **Solution** - we change the `event_hour_min` and `event_hour_max` for multi-day slots to display the full days in the week view - the previous point has the drawback of displaying the full days for non-flexible employees even when not necessary. This is because `slots_start_datetime` and `slots_end_datetime` contained the `planning.slot` start and end. Instead, we can look at the actual slot values displayed (by `_get_slots_vals`). For example, a 5 day slot for a non-flexible employee may contain actual slot values corresponding to a typical 8-17 working day. opw-5245985 Forward-Port-Of: odoo/enterprise#99784
This update ensures shift emails are automatically sent to employees in their preferred language, regardless of the user's language settings. Previously, emails defaulted to the current user's language, causing confusion. This fix improves communication and user experience for international teams.
Original PR description
Steps to reproduce: ------------------------- 1. Install Planning and Contacts. 2. Install any language other than English (e.g., Arabic). 3. Change an employee's contact language to that language.…
Steps to reproduce: ------------------------- 1. Install Planning and Contacts. 2. Install any language other than English (e.g., Arabic). 3. Change an employee's contact language to that language. 4. Create a shift for that employee and click "Send". 5. Check the message in Settings > Technical > Discuss > Messages. Issue: --------- The email is sent in the language of the current user rather than the language of the employee receiving the shift. Cause: --------- The mail template rendering logic ([_render_lang](https://github.com/odoo/odoo/blob/0dbfa8b99d5c28a7d84e781a7f23b226fd964e95/addons/mail/models/mail_render_mixin.py#L549-L566)) fails to determine a valid language on the planning slot record because it is not directly linked to a `partner_id`. As a result, it falls back to the current user's language. Solution: ------------ Explicitly pass the employee partner's language in the mail context so that the email is sent in the correct language. opw-5928676 Forward-Port-Of: odoo/enterprise#110778 Forward-Port-Of: odoo/enterprise#109619