Tuesday, March 17, 2026
12 changes · saas-18.3
Resolved issues and error corrections
This update fixes an issue where Saudi POS orders with both regular sales and settlement lines weren't being properly validated. The recent update to the pos_settle_due module required a change in how settlement lines were identified, but this wasn't initially applied. Now, the validation flow correctly detects and prevents processing of mixed orders, ensuring accurate settlement reporting.
Original PR description
# Description of the issue/feature this PR addresses: From saas-18.3 onward, the pos_settle_due module updated the method used to identify settlement lines from isSettleDueLine() to…
# Description of the issue/feature this PR addresses: From saas-18.3 onward, the pos_settle_due module updated the method used to identify settlement lines from isSettleDueLine() to isAnySettleLine(). This change was not reflected in the Saudi POS EDI integration during forward-porting, which caused incorrect validation when processing POS orders containing both regular sale lines and settlement lines. # Current behavior before PR: - Orders containing a mix of new sale lines and settlement lines could bypass the intended validation. - The validation logic relied on the deprecated isSettleDueLine() method, which is no longer available in newer versions when the pos_settle_due module is installed. # Desired behavior after PR is merged: - Update the validation flow to use isAnySettleLine() (when available) to correctly detect settlement lines. - Prevent validation of POS orders that contain both settlement lines and new sale lines. - Ensure compatibility with newer versions of the pos_settle_due module and restore the intended settlement validation behavior. I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
A bug was preventing portal users from submitting website forms that create tasks. This update resolves an AccessError that occurred when the system tried to access a specific field on the task. The fix uses a temporary workaround to bypass portal access restrictions, ensuring smooth task creation for all users.
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**
This update fixes an issue where multiple email addresses on a contact were being overwritten when creating a helpdesk ticket. The change ensures that a contact's email addresses are correctly captured, resolving a potential data loss problem. This improves the reliability of ticket creation and management.
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 rental income was incorrectly included in the Total Income batch calculation for Hong Kong payroll. The fix removes any rental amounts from this calculation, ensuring accurate reporting and compliance with Hong Kong tax regulations. This improves the reliability of payroll data.
Original PR description
. Removing any rental amounts in calculating Total Income batch task-6006636 Forward-Port-Of: odoo/enterprise#109919
This update fixes a bug where invoices could be created for timesheets that had already been billed. The issue stemmed from the system not correctly tracking and preventing the repeated invoicing of timesheet hours, leading to inaccurate financial records. The fix ensures that invoices are only generated for timesheets that haven't been previously billed.
Original PR description
__ ## Short functional explanation of the error When we create an invoice for a quotation that holds a timesheet product and recorded timesheets for last month. In the wizard, we set the timesheet…
__ ## Short functional explanation of the error When we create an invoice for a quotation that holds a timesheet product and recorded timesheets for last month. In the wizard, we set the timesheet period from the first to the last day of last month. Then, we set the `Invoicing Switch Threshold` to the day of last month. We record another hour for the timesheet, for this product, for today. When we select last month as timesheet period when creating a new invoice, the 2 hours that have already been invoiced are reinvoiced. Moreover, once we confirm this second invoice, it is possible to create again and again invoices for these already invoiced timesheets, without changing the Invoicing Switch Threshold parameter. ## Reproduction Steps 1. Create a quotation. Add as a line a timesheet product. Set the quantity to 2. Validate and click on the smart button Recorded. 2. Record 2 hours with a random date for last month. 3. Create an invoice. In the wizard, set the timesheet period to the first -> the last day of last month. Confirm, and on the invoice form, set the invoice date to last month (after the day on which you recorded the timesheet hours) and confirm. 4. Click on configuration > settings. Search for Invoicing Switch Threshold, and set the date to the last day of last month. 5. Go back to the invoice you created. It should have the ribbon `Ìnvoicing App Legacy`. 6. Go back to the sales order. Click on the smart button Recorded and add one more hour to the timesheets, but this time in February. 7. Create an invoice. On the wizard, set the timesheet period to the first -> last day of last month. Click confirm. ### Expected behavior The system shouldn't let us create an invoice, as we have nothing to invoice, as all the timesheets have already been invoiced. ### Unexpected behavior An invoice is created with 2 hours. It doesn't take into account the hours added in February (normal) but reinvoices the timesheets that have already been invoiced (not normal). ## Origin of the issue When retrieving the quantities to invoice for the timesheets, we don't take into account the quantities already invoiced for the same timesheet. __ opw-5426434 Forward-Port-Of: odoo/odoo#250946
This update resolves an issue where employees were incorrectly appearing in payslip generation reports due to a misinterpretation of contract status. The fix ensures that employees are only included if they have an active contract matching the selected salary structure type, improving the accuracy of payslip calculations. This ensures correct payroll processing.
Original PR description
**Steps to reproduce** - Create an employee - Have a first contract in "New" state covering some period of the month with "Salary Structure Type" A. - Have a second contract in "Running" state…
**Steps to reproduce** - Create an employee - Have a first contract in "New" state covering some period of the month with "Salary Structure Type" A. - Have a second contract in "Running" state covering some other period of the month with "Salary Structure Type" B. - Go to the payslip batch for the current month and click on "Generate payslips". - In the wizard, select "Salary Structure Type" B: employee appears in the list as expected. - In the wizard, select "Salary Structure Type" A. - Unexpected: employee appears in the list, although the contract using that structure type is not in an open or closed state. **Cause** Employees were displayed if they had a contract in open/close state AND a contract with the matching structure type, but we need to check if there's some contract matching both conditions (correct state AND matching structure type). A new function is added to be able to inject an extra domain. opw-5443624 Forward-Port-Of: odoo/enterprise#110027 Forward-Port-Of: odoo/enterprise#104016
This update corrects a bug preventing the partner autocomplete feature from recognizing valid Non-Resident (NRI) GSTINs. The fix updates the validation logic to accommodate newer GSTIN formats, ensuring accurate tax ID input for NRI customers. This improves data accuracy and streamlines the company setup process.
Original PR description
Currently, certain `valid GSTINs` for Non-Resident taxpayers are not recognized by the partner `autocomplete` feature. **Steps to reproduce:** - Install the `l10n_in` and `partner_autocomplete`…
Currently, certain `valid GSTINs` for Non-Resident taxpayers are not recognized by the partner `autocomplete` feature. **Steps to reproduce:** - Install the `l10n_in` and `partner_autocomplete` modules. - Navigate to Settings > Users & Companies > Companies. - Click `New` and set `Tax ID` to `9922JPN29001OSU`. - Wait for 5–10 seconds. **Observation:** The partner autocomplete does not trigger, although it is valid and verifiable on the official GST portal: https://services.gst.gov.in/services/searchtp **Root Cause:** The issue was already fixed in core validation by PR [1], but the GSTIN validation logic used in partner autocomplete was not updated. At [2], the GSTIN validation regex for NRI taxpayers only supports formats ending with `NRX` (X = any alphanumeric character). However, certain valid GSTINs follow a revised structure and therefore are not matched by the existing regex. **Fix**: This commit ensures that valid NRI GSTIN formats are accepted during validation by applying a fix similar to [1] to the partner autocomplete GSTIN validation at [2]. Related IAP PR: https://github.com/odoo/iap-apps/pull/1491 [1]: https://github.com/odoo/odoo/pull/251760 [2]: https://github.com/odoo/odoo/blob/3016c08a7aa8701ec9b0092b5aafc282b16dd9f3/addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js#L36-L52 Forward-Port-Of: odoo/odoo#253799
This update resolves an issue where downpayment products weren't correctly linked to sales order lines. The fix ensures that downpayment products are properly associated with downpayment lines during the sales order creation process, allowing for accurate downpayment tracking and settlement. This improves the functionality of the POS system.
Original PR description
Step to reproduce - install pos_sale - create a SO (make sure it is in draft) - open pos, make sure it has downpayment product - do a downpayment for that SO - go to backend, open SO Observation: - The downpayment product is not linked to downpayment line Cause: - After refactor [1], downpayment product is not added in sale line [1] https://github.com/odoo/odoo/commit/175daa5db6a3f16be6b636a36e2b8462306b2eb4 Fix: - Added the product when creating downpayment line **Note:** - Actual issue reported was different, and was side effect of this issue - there, the downpayment was not considered when trying to settle SO from pos opw-5934461 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update ensures that NACHA payment files accurately reflect the actual account holder's name, rather than the customer's name in Odoo. Prioritizing the bank account holder's name improves payment processing accuracy and compliance with NACHA regulations.
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 fixes a problem where large image uploads would cause errors and disrupt the user experience. Now, uploads can be safely aborted, preventing unexpected behavior and ensuring a cleaner, more reliable image upload process. Users will no longer encounter broken states after attempting to discard an upload.
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
This update resolves an issue where night shift slots (e.g., 20PM - 4AM) were not visible in the weekly planning view. The fix adjusts how the system displays multi-day slots, ensuring that 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 fixes a bug where project timesheets didn't accurately reflect changes in employee costs when switching workers on a manufacturing order. The fix automatically adjusts the AAL (analytic accounting line) linked to the workstation, ensuring correct timesheet calculations and accurate project costing. This improves the reliability of project financial reporting.
Original PR description
### Steps to reproduce: - Create an MTO product and another Service product that create a project and task - Create a quotation with both products - Create two employees with different hourly cost - Go to Manufacturing order - Configure an employee to manufacture the product at a work station. - Observe the project dashboard - Go back to the MO and change the employee on the work station - Notice the project dashboard Timesheets section doesn't have any change on the amount ### Cause: This is happening because when changing the employee we don't modify anything in the AAL linked to the work station. As we only modify the AAL when the duration change. ### Fix: We call _create_analytic_entry when we change the employee on the work station to change the amount and the employee_id for the AAL. opw-5939321 Forward-Port-Of: odoo/enterprise#109695