Thursday, July 24, 2025
12 changes · 18.0
Enhancements to existing features
This update adds tax mapping between Switzerland and EU countries for the EU One Stop Shop module. It helps Swiss businesses selling goods directly to EU consumers configure OSS reporting more easily and reduce manual setup.
Original PR description
Make it easy for any Swiss company that wants to operate B2C sales of goods to customers located in the EU to take advantage of the EU One Stop Shop (OSS) Module, aka l10n_eu_oss_reports. We will ease the discoverability and the configuration Adding the Tax Mapping between Switzerland and the rest of the EU countries task-4943589 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220084 Forward-Port-Of: odoo/odoo#219380
This update improves everyday reliability across Odoo by fixing access handling, notification data consistency, and point of sale troubleshooting. It also enhances the web editor with easier content movement and selection, and adds more flexible date filters for business records.
Online orders from UrbanPiper, Zomato, and Swiggy now calculate and display taxes more accurately based on location and fiscal settings. This helps merchants apply the right tax responsibilities, including special GST handling for India, reducing manual corrections and accounting discrepancies.
Original PR description
**: pos_urban_piper_zomato, pos_urban_piper_swiggy After this commit: --- - For orders outside India, price are received from UrbanPiper as tax-inclusive. Odoo now properly computes the unit price and applies taxes based on the fiscal position. - For India, special handling is implemented: - 5% GST is collected and paid by the aggregator, so only this tax is added via fiscal position mapping. - For other tax rates like 12% or 18%, the merchant is responsible, so these must be configured explicitly in the fiscal position. Note: --- - If a user does **not** want to receive a particular tax in the order, they must manually add a line for it in the fiscal position. Task: 4862417
Resolved issues and error corrections
The Calendar app now correctly filters events by the current user's attendance status, such as accepted or declined. This prevents users from seeing empty search results when matching events actually exist, making calendar management more reliable.
Original PR description
The filter on an event's "Attending?" status was not working correctly. When filtering, the search would always return an empty result set because the underlying search implementation was logically flawed. It incorrectly compared calendar.event IDs with calendar.attendee data, which could never match. This commit corrects the `_search_current_attendee` method to properly query the `calendar.attendee` model. It now finds the intersection of attendees that both belong to the current user and match the filter criteria (e.g., state is 'declined'). It then uses these results to return the correct parent calendar events. A unit test has been added to verify the filter now works as expected. opw-4892386
Italian electronic invoices now remove line breaks from product descriptions before sending them to the SDI tax agency portal. This prevents otherwise valid invoices from being rejected due to unsupported formatting in the description field.
Original PR description
**Steps to reproduce:** 1. Install l10n_it_edi module 2. Create an invoice where the product description includes a newline. 3. Make sure the invoice uses VAT tax. 3. Confirm the invoice. 4. Click on…
**Steps to reproduce:** 1. Install l10n_it_edi module 2. Create an invoice where the product description includes a newline. 3. Make sure the invoice uses VAT tax. 3. Confirm the invoice. 4. Click on send 5. Only enable Send to Tax Agency. 6. Click "Send" again. 7. Go to the Attach files and download the attachment. 8. Check the `<Descrizione>` (description) in the XML file. **Issue:** The `<Descrizione>` field in the `<DettaglioLinee>` tag includes newline characters, which are not accepted by SDI portal. **Causes:** The line description is using '\n'.join(...), which results in actual newline characters in the XML. https://github.com/odoo/odoo/blob/ca7de6b2fbe4626583b67a34d77bbb523d972f79/addons/account/models/account_move_line.py#L513 https://github.com/odoo/odoo/blob/a7a29ed691db4f1607c0d12929c56845681164fa/addons/l10n_it_edi/models/account_move.py#L316-L324 **Solution:** To fix this, replace newline characters in the description with spaces and Strip leading/trailing whitespace. This ensures SDI receives a single-line <Descrizione>value. **Before fix:**  **After fix:**  Ticket [link](https://www.odoo.com/odoo/project/967/tasks/4808826) opw-4808826 co-authored by: Raj Bhuva (bhra@odoo.com)
Fixed an issue in Point of Sale loyalty programs where customers with existing points could still claim a reward after the program's maximum usage limit had already been reached in the session. This helps ensure promotions are applied consistently and prevents unintended extra reward redemptions.
Original PR description
When an existing partner with points tries to claim a reward from a loyalty program that has reached its max usage in the current session, he was still able to claim the reward. Steps to reproduce: ------------------- * Create a loyalty program with max usage set to 1 * Create a partner and assign points to him * Open PoS and select any partner and make an order * Claim the reward from the loyalty program * Select the partner that already has points * Make an order and try to claim the reward again > Observation: The reward can be claimed, even though the max usage is already reached. Why the fix: ------------ When updating programs, we were not removing the couponPointChanges for programs that are not applicable anymore. We now make sure to delete them when the program is not applicable anymore. opw-4805704 Forward-Port-Of: odoo/odoo#218425
This fixes an issue in the website editor where pressing backspace after selecting content across paragraphs could remove text beyond the intended selection. Users can now delete selected editor content without accidentally losing following content.
Original PR description
Problem: Given content like: ``` <p>keep<br>[delete</p> <p>delete<br>delete<br>]</p> <p>keep</p> ``` Pressing backspace removes the last "keep" as well, which is incorrect. Cause: The merge logic uses `range.endContainer` as `joinWith`, but does not account for `range.endOffset`. When `range.endContainer` is a `<p>` with a non-zero offset, the condition `next.previousSibling && next.previousSibling === joinWith` fails. During merging, `next` may go inside `joinWith`, making the logic invalid. Solution: Prevent merging when `next` is positioned exactly at `range.endOffset`, preserving the correct boundary. Steps to reproduce: - Add the sample HTML to the editor - Select from `[delete` to `delete]` - Press backspace -> The final `<p>keep</p>` is deleted incorrectly opw-4905047 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219392
This fixes activity deadline searches so activities already marked as done are no longer counted as overdue or due. It keeps activity lists and CRM follow-up views accurate when completed activities are retained for reporting.
Original PR description
The search for "my_activity_date_deadline" is used to find activities due before some set date. When keeping done activities for reporting purposes, we should never consider "done" activities for this search. Issue is introduced in CRM in [1] but it could happen anywhere task-4951716 [1]: https://github.com/odoo/odoo/commit/f9f0529c93614bb9f9deec1a5aaa1daccfe8b58c Forward-Port-Of: odoo/odoo#219426
Odoo now handles attendance records that cross midnight by splitting them into separate daily work entries. This prevents duplicate or conflicting work entries when an employee has an overnight shift followed by another attendance on the next day.
Original PR description
Steps to reproduce the issue: 0. Set work_entry_source to "attendance" on the running contract of the employee. 1. Create an attendance for yesterday 23:00:00 UTC to today 06:00:00 UTC. 2. Create an…
Steps to reproduce the issue: 0. Set work_entry_source to "attendance" on the running contract of the employee. 1. Create an attendance for yesterday 23:00:00 UTC to today 06:00:00 UTC. 2. Create an attendance today from 08:00:00 UTC to 16:00:00 UTC. Current behavior before PR: Odoo will create a conflicting work entry with the one created in step 1, because the logic recreates all work entries in a timeframe between the start date at 00:00:00 and end date at 23:59:59. The first entry started before this timeframe, so the recreated work entry does not align with the existing one, causing a conflict. Desired behavior after PR is merged: The work entries now span a single day at a time. If an attendance starts at night and ends the next morning, two entries will be created: one from the start time to end of day, and another from the start of the next day to the end time. opw-4869604 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#90588
Mexico payroll and salary offer calculations now handle employees who do not yet have an initial contract start date. This prevents invalid operation errors in the salary configurator and keeps payroll calculations stable by using safe default values.
Original PR description
Before this fix, various computations relying on `employee.first_contract_date` fails if the value was missing, notably: - `_compute_integration_factor` in payslips - Python expressions in MX salary rules (holiday bonus, ISR, etc.) Steps to reproduce: Install the following modules: - Recruitments, Payroll, Salary Configurator - Mexico - Payroll, Mexico - Payroll - Localisation, EDI for Mexico Go to Recruitment -> create or click on application in any offer -> click on generate offer(create a contract templates if needed) -> Click on Salary Configurator, notice the Invalid Operation Error After fix: - Default the integration factor to 1 and years worked to 0 when no start date exists - Safely guard salary rule conditions and computations with proper checks This ensures robust payroll calculation even for employees without an initial contract date. opw-4853613
Portal users can now see published Knowledge articles marked as visible to everyone from the website help page. This fixes an inconsistency where logged-in portal users were blocked from content that anonymous visitors could already view.
Original PR description
There is a bug, when portal user wants to access a article with visibility set to everyone through help page on the website, the portal user wouldn't be able to see anything by clicking on browse…
There is a bug, when portal user wants to access a article with visibility set to everyone through help page on the website, the portal user wouldn't be able to see anything by clicking on browse button, while if the portal users logs out and access the same page, they would be able to see the articles. The steps to reproduce: 1- Setup a database with helpdesk, website, and knowledge app installed. 2- On website app --> help --> Helpdesk Team, enable the knowledge checkbox. 3- Create an article and publish it on the website and set the visibility to everyone. 4- Login as an portal user. 5- Navigate to help page on the website. Click on Browse articles. 6- You can see the article is not shown here. 7- Logout from the portal user and repeat the step 5. You can now see the article. In the current version, if the user is not logged in, they will access the article with visibility set to everyone, which is expected. This is done by returning [] in the _search_is_article_visible. Elsewise, if the user is an internal user, the member_domain and is_article_visible_by_everyone are checked to see if either user has access on the article or the article is visible by everyone. If the user is not an internal user (portal user), the article will be only accessed if they are a member of the article, without checking article's visibility, which causes the bug. opw-4835998
Zero-cost Brazilian point-of-sale orders now include the required payment information when sent for electronic invoicing. This prevents Avalara submission errors and helps ensure free or fully discounted sales can still be invoiced correctly.
Original PR description
Right now, for 0 cost POS orders no `paymentMode` section is sent to Avalara, which leads to an error from them when trying to submit the invoice: Code 899: incorrectly entered payment method field The proper fix is to always send `paymentMode` with a value of 0.00 and mode of `Other`. (Note that there is a payment mode that corresponds to no payment, 90, but it only available for NF-e not NFC-e so we use 99) opw-4874094