Daily updates from Odoo
Navigate
Branch
Monday, August 11, 2025
55 changes
21 changes
New functionality added to Odoo
Shared project users can now view and schedule tasks in a Gantt timeline, making it easier for stakeholders to coordinate work assigned by project managers. The update supports drag-and-drop scheduling in shared projects and opens the appropriate sharing form when tasks are edited.
Original PR description
### Purpose: The main objective of this task is to allow stakeholders to efficiently manage shared projects assigned by the project manager. ### Changes Implemented: - Added Gantt view in project…
### Purpose:
The main objective of this task is to allow stakeholders to efficiently manage shared projects assigned by the project manager.
### Changes Implemented:
- Added Gantt view in project sharing.
- Stakeholders can schedule multiple tasks.
- Drag-and-drop is enabled when grouped by stage or tag.
- Dependency lines are visible only in read-only mode.
- Editing a task opens the project sharing form view.
### Technical Details:
- Mail-related dependencies are not loaded in project sharing and require a common renderer.
Updated Renderer Structure:
GanttRenderer
|
TaskGanttRendererCommon
|
-------------------------------------------
| |
TaskGanttRenderer TaskSharingGanttRenderer
-----------------------------------------------------------------------------
Updated Model Structure:
GanttModel
|
TaskGanttModelCommon
|
-----------------------------------
| |
TaskGanttModel TaskSharingGanttModel
------------------------------------------------------------------
Updated GanttArchParser Structure:
GanttArchParser
|
TaskGanttArchParserCommon
|
---------------------------------------------------
| |
TaskGanttArchParser TaskSharingGanttArchParser
task-4489162Sales teams can now view quotations and sales orders on a map and use routing support. This makes it easier to plan visits or deliveries around customer locations directly from the Sales app.
Original PR description
Description of the issue/feature this PR addresses: Add map view and routing features to Sales modules. Current behavior before PR: - Sales Orders and Quotations had no map or routing support Desired behavior after PR is merged: - Sales Orders and Quotations support map view and routing. See Also: - Community PR: https://github.com/odoo/odoo/pull/204805 Task-4402920 I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Enhancements to existing features
Odoo now attempts to recover an active video call from another open browser tab when the original tab is closed. This reduces accidental call interruptions and improves reliability when users work across multiple tabs.
Original PR description
When a video call is ongoing and the user closes the tab, a recover is attempted by another available browser tab (if any). Improvements have been made to the multi_tab_service to prevent inconsistent election results. Task-3244140 https://github.com/odoo/odoo/pull/174201
This update keeps the appointment website feature aligned with a recent platform change. It helps ensure appointment snippets continue working correctly without changing the customer-facing experience.
Original PR description
This PR updates the `_prepare_values` method to include the new `offset` argument, aligning with the updated super method in `WebsiteSnippetFilter` class. task-4236245
The Dutch Tax Report layout has been improved to make amounts easier to understand. It reduces visual clutter by separating tax amounts into a distinct column and better distinguishing base amounts from tax amounts, including for XBRL reporting.
Original PR description
The Dutch Tax Report Can be Improved - less lines by adding a distinct tax col - clear distinction between base amount and tax amount --- This is fixing the XBRL report after this PR: https://github.com/odoo/odoo/pull/222292 task-5000683
The bank reconciliation statement button has been moved to the right side of each statement line. This prevents it from overlapping with other actions on smaller screens, making the interface easier and safer to use.
Original PR description
This commit will move the statement button on the right of the statement line because when having a small screen the button was at the place of the other button of the statement line which could cause problems for the users to click on it task: 5004109 Forward-Port-Of: odoo/enterprise#91981
Users now see the thank-you dialog whenever a signing document is completed, not just the first time. People who are not signed in can also access their other signature requests from that dialog, making it easier to complete pending documents.
Original PR description
Before this commit, it was only displayed once.
Moreover this PR adds the possibility for non signed in users to see their other sign request.
task 4854650Website themes can now include the appointments section directly in their setup flow. This lets users add appointment booking content through the website configurator instead of manually editing HTML, making setup faster and less technical.
Original PR description
Desired behavior after PR is merged: - Adapted 's_appointments' dynamic snippet to be included in a theme's manifest. As a result, the snippet can be added to the website via the configurator, without needing manual insertion via the HTML editor. Related: https://github.com/odoo/odoo/pull/203436 task-4502087
The subscription app's empty screen now uses a larger, more readable illustration. This improves the first-time or no-data experience by making the guidance visual easier to understand in both light and dark modes.
Original PR description
Before this commit, the empty screen image was too small and unreadable. This commit update the image with a more readable empty screen image. <details> <summary>Preview Changes</summary> | Before | After | |--------|--------| | <img width="1207" height="935" alt="old_light_mode" src="https://github.com/user-attachments/assets/4df6738e-dcc4-4de0-99ae-b8a33bda6f76" /> | <img width="1207" height="935" alt="new_light_mode" src="https://github.com/user-attachments/assets/a56bbe33-2db9-4c9e-b1b4-d3d8fc717bed" /> | | <img width="1207" height="935" alt="old_dark_mode" src="https://github.com/user-attachments/assets/20ae2350-c126-4eda-8c74-c1121dae53fc" /> | <img width="1207" height="935" alt="new_dark_mode" src="https://github.com/user-attachments/assets/d8ef0691-0d3f-4304-a9d2-60eb33ac40eb" /> | </details> task-4912109
IoT Box images no longer use the previous read-only storage mode that required repeated switching before writing data. This removes an ineffective process that was often left in writable mode anyway, improving reliability and reducing operational complexity.
Original PR description
IoT Box images were r/o by default: we had to remount the filesystem r/w everytime we wanted to write something. As it was getting hard to track background processes keeping mount points busy, we removed the logic. In addition, as mount points were kept busy, IoT Boxes stayed in r/w mode all the time, making the logic useless. Community PR: odoo/odoo#216014 Task: 4551009
The VoIP call list no longer offers a create option for adding call records from the backend. This keeps the list as an accurate log of calls made through the VoIP widget and reduces the risk of manual or misleading entries.
Original PR description
Purpose: Creating a new voip.call record from the backend should not be allowed. Since it is a log of the calls that are taking place via the widget. Specification: Removed the option to create records from call list view. Task-4988885
The appointment calendar event form has been redesigned to make appointment status clearer and easier to update. Users can now see status ribbons, use quick action buttons, and manage relevant resources or staff capacity more easily from the event form.
Original PR description
Enterprise counterpart to the redesign of the calendar event form view. Main changes (when appointment_type_id is set): - Add ribbons for various appointment_status values - Add buttons in the header to quickly update the status, with a displayed according to the status, and associated actions on the model. - Improve the 'resources' notebook page to display user or resources depending on the type of appointment the meeting is related to. This allows edition of booked capacity while displaying relevant information. COM PR : https://github.com/odoo/odoo/pull/219677 UPG PR : odoo/upgrade#8160 Task-4929768
Contacts now show how many active subscriptions are linked to them when the Subscriptions app is installed. This gives teams a clearer view of customer activity alongside existing contact statistics, without affecting users who do not use subscriptions.
Original PR description
The PR adds a new statistics to contacts when the subscription app is installed. Together with the number of sales on each contact and any other stat defined by other modules installed, the number of subscriptions is now shown in the Stat field of the contacts that have any active subs. This happens only if the subscription module is installed. Task-4934773
Helpdesk users can now update a ticket's stage directly from the list view when the selected tickets all belong to the same team. This makes bulk updates faster while preventing incorrect stage changes across teams with different workflows.
Original PR description
Before this commit: The stage field was always readonly in the list view, preventing users from changing the stage of a ticket, whether selecting a single record or multiple records. After this commit: The stage field becomes editable in the list view if all selected tickets belong to the same team. If the selection includes tickets from different teams, the field will be readonly to prevent inconsistent stage updates. task-4775290
Resolved issues and error corrections
Confirming a rental order with plannable products now continues creating all possible planning shifts even if one line has no available resource. This prevents incomplete planning from being generated and helps teams avoid missing scheduled rental work.
Original PR description
Before this commit, when rental order containing a plannable rental product is confirmed, some shifts will be generated according to the rental order lines with such product. The problem is when there is no available resource, the method in which we expect to return vals list of planning.slot model will return vals because it will break the loop instead of continuing to the next iteration. This commit makes sure the `_planning_slot_vals_list` always return list of vals. Forward-Port-Of: odoo/enterprise#92030
Fixes the Czech VIES summary report so invoice counts, transaction labels, grouping, and rounded totals match official reporting requirements. This helps businesses submit more accurate VAT-related reports and reduces the risk of incorrect filings.
Original PR description
There are some errors in the VIES summary report fixed here:
1. The supply number is not the quantity invoiced, it is the
number of invoices
2. There was some confusion between the terms "supply transaction"
and "supply code", with "supply code" not being used
in this report (but still in Python code to avoid breaking stable versions)
3. We were considering journal items, whereas it is preferable
to group them by journal entry
4. The total value is rounded up to the nearest whole crown (Czech currency)
Here is a link to the documentation:
adisspr.mfcr.cz/dpr/adis/idpr_pub/epo2_info/popis_struktury_detail.faces?zkratka=DPHSHV
where pln_hodnota is the total value; pln_pocet is the supply number; and k_pln_eu is the supply transaction.
opw-4688616
Forward-Port-Of: odoo/enterprise#91891
Forward-Port-Of: odoo/enterprise#88279The Swedish SIE4 import now avoids creating accounting entries when the source file contains no usable transaction lines. This prevents empty journal entries from being added to Odoo, keeping imported accounting data cleaner and more reliable.
Original PR description
The aim of this commit is making sure that we don't import move without transaction in it. In SIE4, we can have moves with BTRANS and RTRANS tags that we are ignoring. It means that we could have move without any move lines. It's not an expected behavior in Odoo. This commit checks that the move data are created only if we have lines for that move. no task id Forward-Port-Of: odoo/enterprise#91783
Project profitability now includes amounts invoiced before a subscription was renewed. This prevents renewed subscriptions from making project revenue look too low, giving teams a more accurate profitability view.
Original PR description
To reproduce: ============= - create a subscription with a service and link it to a project - confirm the subscription and invoice it - check the profitability of the project, everything is fine - renew the subscription and invoice it - check the profitability of the project, the invoiced amount is not taking into account the previous invoiced amount Problem: ======== renewed subscriptions are excluded from the profitability computation because they are closed by the renewal and not bringing any profitability, but with that we loose the profitability of the previous invoiced amount. Solution: ========= keep renewed subscriptions in computing `Invoiced` amount. opw-4755016 Forward-Port-Of: odoo/enterprise#92052 Forward-Port-Of: odoo/enterprise#91437
Invoices and bills now show related bank transactions from the same partner in the payment widget, making it easier to match payments without switching screens. This fixes where the payment widget logic lives so the feature is available in the correct accounting module and avoids incorrect outstanding payment calculations.
Original PR description
Removed the bank statement lines in the payment widget from communiy 'account' and added it to 'account_accountant' Community: https://github.com/odoo/odoo/pull/220981 Forward-Port-Of: odoo/enterprise#91451 Forward-Port-Of: odoo/enterprise#91222
Recruitment users can now rename salary offers without the title reverting after saving. This ensures offer records reflect the intended names and reduces confusion when managing applications.
Original PR description
Steps to produce: - Navigate to Recruitment > Job Positions > Applications> Offers - Select an offer and try to edit the title and save Issues: - When the title is edited and saved, the title reverts back to previous name. Fix: - Change the field attribute in model by making it store=True task-4787302
This fix prevents original list prices from being exposed in hidden page elements for rental products that are not available for sale at zero price. It helps keep website pricing behavior consistent for visitors and avoids search engines or page inspection revealing prices that should not be shown.
Original PR description
Versions
--------
- 17.0+
Steps
-----
1. Create a pricelist setting product prices to zero;
2. configure website to make zero-priced products unavailable for sale;
3. go to /shop as a public user;
4. open the product page of a zero-priced product;
5. open the browser console;
6. use `document.querySelector('.css_non_editable_mode_hidden .oe_currency_value')`
Issue
-----
The query returns an element with the product's original list price.
Cause
-----
In `website_sale`, this element is part of a `t-if` that only gets rendered when `editable` is `True`. A `website_sale_renting` override changes the conditional to `not combination_info.get('is_rental')`.
Solution
--------
Instead of replacing the `t-if` attribute in the override, add `and not combination_info.get('is_rental')` to it, ensuring it remains hidden outside of editable mode.
opw-4865141
Forward-Port-Of: odoo/enterprise#91826
Forward-Port-Of: odoo/enterprise#9111234 changes
New functionality added to Odoo
This update adds support for an additional IVA tax rate in the Uruguay localization. It helps businesses using Odoo in Uruguay record and report transactions that fall under this other VAT rate more accurately.
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
Enhancements to existing features
Company branches in Saudi localization will no longer automatically reuse the parent company's e-invoicing API mode or private key. This helps each branch maintain its own compliant ZATCA setup and avoids incorrect sharing of sensitive configuration between related companies.
Original PR description
Description of the issue/feature this PR addresses: When a branch is created for a company it inherits the `l10n_sa_private_key` and `l10n_sa_api_mode` of the parent company, which is which is incorrect and non-compliant from both an Odoo workflow and ZATCA's perspective Current behavior before PR: When you try to create a branch, it automatically inherits the `l10n_sa_api_mode` and `l10n_sa_private_key` of the parent company. Desired behavior after PR is merged: When you try to create a branch, its `l10n_sa_api_mode` and `l10n_sa_private_key` will be independent from the parent company. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222159
Romanian localization now includes the new 11% and 21% VAT rates and related tax groups introduced by recent legislation. Existing tax group assignments were also aligned for more consistent reporting and tax configuration.
Original PR description
This PR adds new taxes and tax groups for 11% and 21% after new VAT law was introduced in Romania. It also fixes tax groups of some taxes and make it more consistent. TaskID:4979168 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221238
Updates Romanian SAF-T reporting data so newly introduced taxes are classified with the correct tax type and code. This helps businesses stay aligned with recent Romanian tax law changes and keeps SAF-T report outputs accurate.
Original PR description
New taxes were introduced in Romania as per the new tax Law. The PR https://github.com/odoo/odoo/pull/221238/files added new taxes in community. This PR updates the SAF-T Tax Type and Code for the newly added taxes. TaskID:4979168 Forward-Port-Of: odoo/enterprise#91512
This update expands the Shopee sales connector so businesses can synchronize their product catalogue and inventory with Shopee more effectively. It helps reduce manual marketplace management and keeps online sales data better aligned with Odoo.
Original PR description
Adding new features: - Sync product catalogue - Inventory task - 4717989
Resolved issues and error corrections
Paid time off in the French localization now uses the employee's actual work schedule when calculating hours, instead of defaulting to the company's schedule. This prevents timesheets from underreporting leave hours when an employee works longer days than the company default, while keeping French leave day-count rules intact.
Original PR description
With the French fiscal localization: When an employee has a different working schedule than the company’s default one. If the employee’s daily working hours are greater than the company’s default…
With the French fiscal localization: When an employee has a different working schedule than the company’s default one. If the employee’s daily working hours are greater than the company’s default hours. The timesheet for paid time off only displays the company’s default hours instead of the employee’s actual hours. Steps to reproduce: ------------------- * Install l10n_fr_hr_holidays * Set the French fiscal localization * Working schedule of the company -> 7:30 per day * Working schedule of the employee -> 8 per day * Create a paid time-off with this employee * Check the Timesheet of this employee > Observation: Timesheet shows 7:30 instead of 8 Why the fix: ------------ We needed to ensure the hours are always calculated correctly (using the employee’s or company’s calendar when appropriate) while still forcing the correct day count (1 or 0.5) and extending it according to French law. ✅ Day count is forced (0.5 or 1) depending on the leave type. ✅ Hours are fetched from `super()._get_durations()` so the timesheet keeps accurate hours. This prevents timesheets from showing incorrect hours when the employee's work schedule differs from the company's work schedule. opw-4744516 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Portal users sharing Microsoft Office documents will now have the file type saved consistently with the corrected file name. This prevents Office files such as spreadsheets from being treated as zip files, allowing users to open and work with them as expected in Odoo.
Original PR description
Issue: Inconsistent mimetype vs filename for documents shared by portal users. 1. Share a ms office document logged in as a portal user. 2. filename is correct, but mimetype is `application/zip`. 3.…
Issue: Inconsistent mimetype vs filename for documents shared by portal users. 1. Share a ms office document logged in as a portal user. 2. filename is correct, but mimetype is `application/zip`. 3. User can't interact with the file to open the file in the Odoo spreadsheet because the mimetype is zip. <img width="387" height="192" alt="image" src="https://github.com/user-attachments/assets/be31f05f-e4e3-44d9-b12a-66f96feba950" /> <img width="274" height="67" alt="image" src="https://github.com/user-attachments/assets/93064e5c-c028-41ce-8e79-1b9c9447c018" /> With `fix_filename_extension()`, the following two commits fixed the issue of Odoo's `guess_mimetype` function incorrectly guessing extensions such as `.xlsx` as `.zip` extension. https://github.com/odoo/odoo/commit/8842b6b43e7c3d1cc67d7d399bb210e4009e23b2 https://github.com/odoo/odoo/commit/34d9375e2efb604f8e7036cb710f44b01f9ccaee However, the `_from_request_file()` still uses the incorrectly guessed mimetype to create an attachment, leading to inconsistent extension from the filename (.xlsx) vs attachment record's mimetype (.zip). This commit fixes the issue by using the mimetype from the filename's extension. This is safe if the following assumption is correct: At the point where the `from_request_file()` attempts to create the attachment record, the `filename` contains correct extension name, presumably fixed by the `fix_filename_extension()`. Commit message to be changed after with Julien's confirmation; opw-4753670 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes incorrect access information being shown for portal document conversations. Users accessing documents through shared portal links will now get accurate permissions, helping avoid misleading interface options.
Original PR description
Before this commit, the `_thread_to_store` method would always set the `hasReadAccess` property to true. This was fine because the only flow that would add the values to the store would already check the existance and access to the thread. However after change [1] the access values would be sent in more flows, one of which being portal chatter initialization. This causes the client to have incorrect access information to the thread (i.e. hasReadAccess would be true even when accessing portal document through token). This commit fixes the issue by sending the correct access values. [1] https://github.com/odoo/odoo/pull/220774
Purchase orders now choose the vendor pricing rule that matches the ordered quantity instead of simply picking the cheapest rule for the same vendor. This prevents incorrect low-volume purchases from being priced with bulk discounts meant for larger quantities.
Original PR description
Steps to reproduce the bug: - Create a storable product “P1” - Under the Purchase tab: - add two vendor pricelist entries: 1:/ - Vendor: Azure Interior - min_qty: 1 - Price: $5 2:/ - Vendor: Azure…
Steps to reproduce the bug:
- Create a storable product “P1”
- Under the Purchase tab:
- add two vendor pricelist entries:
1:/
- Vendor: Azure Interior
- min_qty: 1
- Price: $5
2:/
- Vendor: Azure Interior
- min_qty: 100
- Price: $2
- Create a purchase order:
- vendor: Azure Interior
- Try to add the product P1
**Problem:**
When adding a product to a purchase order, if multiple supplier info
lines exist for the same vendor, the one with the lowest price will be
selected, instead of the one matching the smallest applicable quantity
(min_qty).
This regression was introduced by the following commit, which
tried to fix an unrelated bug with supplier info date matching:
https://github.com/odoo/odoo/commit/7eabfcff402993f32f5c835e18e07c91782a7b33#diff-5684edced9bdfc98021a85de4c6cdf691ea7add74e56ab50334a1d7db9ef4224L470
As part of that fix, the logic was changed to use the _select_seller
method, which by default sorts supplier info lines by price_discounted
and returns the first one — regardless of whether the min_qty is met.
Previously, the logic correctly selected the supplier line based
on min_qty when multiple lines existed for the same vendor.
**_Note:_** This bug is no longer present as of version 18.1, because
the date-related issue was fixed differently in the following commit:
https://github.com/odoo/odoo/commit/19c65c4884a3746b44b6272694662eb32a6bf32f
That later fix preserved the original behavior of respecting min_qty.
**Solution:**
Explicitly pass ordered_by='min_qty' when calling _select_seller.
This ensures that supplier info lines are prioritized based on the
lowest applicable min_qty, not the lowest price, when the vendor is the
same.
opw-4942819
Forward-Port-Of: odoo/odoo#221764Quotation PDF templates now correctly display numeric fields when their value is zero. This prevents customers from seeing blank fields where a valid zero amount or quantity should be shown.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Using Studio, add an integer or float field to the sale order form; 2. upload a PDF using forms as a quotation header[^1]; 3. add a mapping of the form field to the studio field; 4. create a quoation using the header; 5. have the studio field be 0; 6. print quotation. [^1]: e.g. `tests/files/test_forms.pdf` Issue ----- The form field where the zero should be displayed is empty. Cause ----- When formatting values, it returns an empty string for any falsy value whose field isn't of type boolean or monetary. Solution -------- If the value is falsy, only return the empty string if the field type is not integer or float, this way, the zero value will get formatted in the final `else` as a string value (same as non-zero numeric values). opw-4937052
This fixes a Point of Sale issue where orders from a closed session could fail to invoice when cash rounding was involved. Businesses can now create invoices for these POS orders reliably, avoiding blocked accounting workflows caused by unbalanced entries.
Original PR description
Currently it's not always possible to invoice an order from another sessio nthat is already closed when there is cash rounding. Steps to reproduce: ------------------- * Enable cash rounding for cash methods only, 5cents half-up * Open pos session * Add a produc with price 174.99 to order * Add a customer * Go to pay * Select pm cash and enter 100 * Select pm bank and enter 75 * Change 0.01 * Validate * Close session * Open session * Try invoicing the precedent order > Observation: Not possible to invoice, move is not balanced Back porting as it is exaclty the same issue: https://github.com/odoo/odoo/commit/626c3fd1bff85cc6cb222bdba80c14dd761dafd3 opw-[4829919](https://www.odoo.com/web#id=4829919&view_type=form&model=project.task) Forward-Port-Of: odoo/odoo#220096
Contacts without a name or email now show their available display name in chatter recipient and follower lists instead of appearing blank or as “false”. This prevents confusion when adding invoice-address contacts or followers to messages and makes recipient selection clearer.
Original PR description
Steps to reproduce =============== 1. Create a contact of type invoice address without name and email. 2. Go to any app with chatter. 3. Add this user to the recipient ----> Only the blue tick will be visible (recipient name will be empty) After this commit, we will use the display_name as a fallback to show in the chatter.
This fix ensures operations covered by articles 22, 23 and 24 are included in section 60 of Spain's Model 303 VAT report. It helps Spanish companies produce more accurate VAT declarations and reduces the risk of incorrect tax reporting.
Original PR description
Operations included in articles 22, 23 and 24 should be included in section 60 of the model 303 report: source: https://declarando.es/modelo-303/casillas-59-60-y-61? opw-4954870 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#221686
This fixes a calendar test setup so it uses valid default event information when checking a fallback case. The change helps keep automated validation reliable and reduces the risk of false failures during updates.
Original PR description
Use valid res_model/res_id in context defaults runbot-235289 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222426
Sales order lines now refresh the unit price when a quantity change qualifies for a different pricelist rule. This prevents customers from being quoted outdated prices and helps sales teams apply configured pricing consistently.
Original PR description
**Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: -…
**Steps to reproduce**:
1. Install the `sale` module.
2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`.
3. Create two pricelists:
- Pricelist A with two fixed-price rules:
- `0.75` for quantity ≥ 0
- `0.50` for quantity ≥ 1000
- Pricelist B with a `-10%` discount applied to Pricelist A.
4. Create a Sales Order using Pricelist B.
5. Add a product to the order line.
6. Increase the quantity to 1000.
**Observed behavior**:
- The unit price does not update according to the pricelist rule for quantity ≥ 1000.
- If you switch the pricelist to another and then back again, the `Update prices` button appears and correctly updates the price.
**Root cause**:
- The price is not recomputed when the quantity changes because the `price_unit` is not updated because it does not match the `technical_price_unit`.
- Since PR [#21392](https://github.com/odoo/odoo/pull/213912), `price_unit` is rounded (2 decimals), but `technical_price_unit` is not. This causes a mismatch in comparison logic due to rounding differences.
**Solution**:
- Replace direct float comparison with `currency_id.compare_amounts()` to ensure proper comparison with rounding precision.
opw-4944644Review and rating popups now stay aligned with the related discussion thread across portal pages, course pages, and chat components. This fixes inconsistent review editing or display behavior, giving users a more reliable feedback experience.
Original PR description
portal, portal_rating, rating, website_slides task-4743757
Leave requests for employees with flexible working hours now correctly count as zero days when they fall on a public holiday. This prevents employees' leave balances from being reduced for days that should not require time off.
Original PR description
**Steps to reproduce:** 1) Create a flexible working schedule. 2) Assign this schedule to an employee. 3) Create a public holiday. 4) Create a leave request for the flexible employee on the public…
**Steps to reproduce:** 1) Create a flexible working schedule. 2) Assign this schedule to an employee. 3) Create a public holiday. 4) Create a leave request for the flexible employee on the public holiday. 5) Notice that the duration of the leave is 1 instead of 0. **Issue:** Due to recent changes in the [commit](https://github.com/odoo/odoo/commit/a826f65c2d95b796f919023d560ec9f0801090d8#diff-38469def2f870bb866f971f57797dd7c21b6a95d52a8eae72f832f0eea2434f9R427-R433) , When a single-day flexible leave is taken, the duration is always set to the real duration. However, we do not check if the leave falls on a public holiday, which results in the leave being set to 1 day, even on holidays. https://github.com/odoo/odoo/blob/8f24da78f60529ea0b1840e48de30e15d17ddb77/addons/hr_holidays/models/hr_leave.py#L427-L433 **For example:** If Christmas is marked as a public holiday and an employee with a flexible schedule requests a one-day leave on Christmas, the leave is recorded with a duration of 1 day. **Fix:** Check for a public holiday on leave date; if yes, set leave duration to 0. opw-4963122
Internal users without administrator rights can now send Spanish FacturaE invoices without encountering an access error. This removes an unnecessary permission blocker in the invoicing workflow while keeping certificate handling consistent with existing behavior.
Original PR description
Non-admin users were hitting an “Access Error” when sending an invoice in facturae format, the onchange reads `company.l10n_es_edi_facturae_certificate_ids`, which reads certificate.certificate…
Non-admin users were hitting an “Access Error” when sending an invoice in facturae format, the onchange reads `company.l10n_es_edi_facturae_certificate_ids`, which reads certificate.certificate records , resulting in an “Access Error” popup. This changes Wrap the certificate lookup in company.sudo(). It's handled the same in https://github.com/odoo/odoo/blob/18.0/addons/l10n_es_edi_facturae/models/account_move.py#L140 https://github.com/odoo/odoo/blob/18.0/addons/l10n_es_edi_facturae/models/account_move.py#L770 install l10n_es_edi_facturae Go to Contacts and create an new contact with Spain as country in the same page (creating contact page) click on Accounting scroll down and set eInvoice format as facturaE Go to Accountant and create an invoice with that client pay the invoice log out and log in with a user with no administration (e.g. Marc demo) try to send the create invoice OPW:4989007 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents the background invoice sending process from failing when an invoice is changed back to draft or canceled before it is sent. It ensures only valid posted invoices are processed and clears outdated sending information, improving reliability for accounting workflows.
Original PR description
This commit makes the asynchronous invoice sending process more robust. Previously, the `_cron_account_move_send` method would fail if it encountered an invoice that was not in a 'posted' state. This could happen if a user changed the state of an invoice back to 'draft' or 'canceled' after it was selected for sending but before the cron job ran. To fix this, we added an extra condition to the search domain, so that only posted invoices are accounted for. We also added an explicit reset of `sending_data` in the draft button method, so that setting a posted invoiced back to draft does not retain (outdated) sending data. Steps to reproduce: 1. Select posted invoices and send. 2. Before cron runs, set one invoice to 'draft'. 3. Manually run the cron job `_cron_account_move_send`. 4. Observe the traceback. OPW-4985528 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an accounting issue where manually adjusting and then restoring a tax amount on Portuguese vendor bills could incorrectly reduce the untaxed total by one cent. This helps keep invoice totals accurate and prevents small but confusing accounting discrepancies.
Original PR description
**Issue** When using the Portuguese localization (`l10n_pt`), manually changing and resetting a tax amount on a vendor bill can incorrectly alter the base (untaxed) amount. **Steps to Reproduce** 1.…
**Issue** When using the Portuguese localization (`l10n_pt`), manually changing and resetting a tax amount on a vendor bill can incorrectly alter the base (untaxed) amount. **Steps to Reproduce** 1. Install Accounting and Portuguese localization (`l10n_pt`) 2. Create a vendor bill with a line: price = 123, tax = 23% 3. Manually change the computed tax amount from 28.29 to 28.30 4. Change it back to 28.29 5. Save the invoice 6. Observe that the untaxed amount becomes 122.99 instead of 123.00 **Root Cause** In the Portuguese localization, the tax delta logic compares `raw_total_amount` instead of `raw_base_amount` to detect rounding differences. However, the `raw_total_amount` field is not recomputed when the tax amount is manually edited. As a result, the system detects a false positive delta (0.01) and incorrectly subtracts it from the base amount to force reconciliation of totals. **Fix** Extend the delta correction loop to also update `raw_total_amount` and `raw_total_amount_currency`, not just `tax_amount` and `tax_amount_currency`. This ensures all totals are correctly adjusted after a manual tax change, and prevents the base amount from being unintentionally altered. Opw-4943540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Calendar events can now sync to Google even when a multi-company user handles an event organized by someone with access to only one company. The sync now uses the organizer’s valid company context, preventing access errors and reducing disruption for teams using multiple companies.
Original PR description
**Description** When syncing a calendar event to Google, the system impersonates the event organizer in a multi-company context, this causes an access error if the current context includes companies…
**Description** When syncing a calendar event to Google, the system impersonates the event organizer in a multi-company context, this causes an access error if the current context includes companies the organizer does not have access to. --- **Steps to Reproduce** - Create Company B and organizer user (Company A access only) - Set current user to have access to both companies - Login as the organizer user - Go to Calendar app - Create a new event with Google sync enabled - Login as multi-company user - Select both companies in company switcher - Navigate to the event created by organizer - Trigger Google Calendar sync (accept/decline event) --- **Before** ` Access to unauthorized or invalid companies` **Root cause:** - The sync switches to the organizer's identity but keeps the original multi-company context - This creates a mismatch where the organizer doesn't have access to all companies in the context - Results in access violation when trying to sync **After:** - Properly scope the company context to match the organizer's company when switching user identity - This ensures the sync operation runs within the correct company boundaries opw-4911040 Forward-Port-Of: odoo/odoo#221193
Project profitability figures now use the accounting line balance, avoiding incorrect currency conversions based on today's or manually changed exchange rates. This makes project dashboards align more reliably with analytic accounting reports, especially for foreign-currency vendor bills or historical transactions.
Original PR description
Issue description: The profitability items for projects were not matching the numbers from analytic accounting reports due to discrepancies in currency rate calculations. This issue was traced to two…
Issue description: The profitability items for projects were not matching the numbers from analytic accounting reports due to discrepancies in currency rate calculations. This issue was traced to two main causes: 1. Profitability items were using the currency rate of today, even for old move lines. ```rates = self.env['res.currency'].browse(list(currency_ids))._get_rates(self.company_id, date.today())``` While this was deemed acceptable for performance reasons in #113146, it caused mismatches with analytic accounting reports. 2. Some move lines use a changed currency rate that differs from the rate stored in the currency table for the same date (due to manual change in the currency rate), leading to further mismatches. To resolve this: - The `balance` is now used instead of `price_subtotal` for calculations. This ensures accurate amounts without relying on conversion rates when the project currency matches the company currency. Steps to Reproduce: 1. Create a project with an associated analytic account. 2. Enable any foreign currency and add different rates for it for today and yesterday. 3. Create a new vendor bill with: - Date = yesterday - Currency = the new foreign currency - Analytic distribution set to the created project's analytic account. 4. Check the project dashboard profitability. You will see the numbers are incorrect because it uses the currency rate of today. opw - 4881380 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221168 Forward-Port-Of: odoo/odoo#217337
Incoming return slips now show the correct destination address instead of placeholder demo text. This prevents confusion for warehouse teams and partners when printing return documentation for receipts.
Original PR description
Issue ----- Incoming return slips have a "Demo Address and Name" text instead of the correct destination address. <img width="928" height="658" alt="image"…
Issue ----- Incoming return slips have a "Demo Address and Name" text instead of the correct destination address. <img width="928" height="658" alt="image" src="https://github.com/user-attachments/assets/6ff0a5e7-f1ee-4faa-a22b-76ec8f2f7a28" /> Steps to reproduce ----- - Create a receipt for a product - Print its return slip Cause ----- By default, the address is taken from the pickings location_id -> warehouse_id -> partner_id. For incoming pickings, the warehouse is the vendor one, with no associated partner. In such cases, the partner can be found directly on the picking itself with the partner_id field. Note ----- To render t-fields, qweb first applies a `rsplit` before evaluating the expression, see https://github.com/odoo/odoo/blob/cb1c761777e84d96f82c4f754586795509ce1b3d/odoo/addons/base/models/ir_qweb.py#L2015-L2016 With this in mind, using parentheses and moving `.partner_id` outside of them seems like the most readable way to go about it. ----- Ticket: opw-4660716 Forward-Port-Of: odoo/odoo#219011
This fixes an error when exporting Spanish VAT record books for invoices using the 0.26% or 1% equivalence surcharge purchase taxes. Businesses in Spain can now generate the VAT book XLSX report for these cases without the process failing.
Original PR description
Added to SURCHARGE_TAX_EQUIVALENT taxes 0.26% SE and 1% SE When using the Odoo VAT book (location Spain) and we have an invoice with the taxes 0.26% SE (0,26% Recargo Equivalencia Compras) 1% SE (1%…
Added to SURCHARGE_TAX_EQUIVALENT taxes 0.26% SE and 1% SE When using the Odoo VAT book (location Spain) and we have an invoice with the taxes 0.26% SE (0,26% Recargo Equivalencia Compras) 1% SE (1% Recargo Equivalencia Compras). a KeyError error occurs <img width="1147" height="517" alt="Captura desde 2025-07-30 09-37-13" src="https://github.com/user-attachments/assets/771fcf6e-efed-4e79-a1d4-a133c7072c2a" /> Steps to Reproduce this error: 1. Create a new database using Odoo version 18. 2. Activate the module: “Spain - Accounting (PGCE 2008)” (l10n_es). 3. Create a new company and set Spain as the country. 4. In the company’s “Sales & Purchase” tab, set the Fiscal Position to "Equivalence surcharge". 5. Create a new quotation and select the company created in step 3. 6. Add a product with the following taxes: 0.26% and 2% VAT (G). 7. Add another product with the following taxes: 1% (SE) and 7.5% VAT (G). 8. Confirm the invoice generated from the quotation. 9. Go to Accounting → Reporting → Tax Report and select "Generic Tax Report". 10. Click the gear icon and select "VAT Record Books (XLSX)". OPW https://www.odoo.com/es_ES/my/tasks/4981807 @jco-odoo please review. Thank you! MT-10457 @moduon
The Web Studio test suite was updated to match a recent change in how suggested message recipients are returned. This helps keep automated checks reliable and reduces the risk of false test failures during future updates.
Original PR description
From the related community commit, the _message_add_suggested_recipient method is modified to also return display name under certain condition. This commit adapts the test inside web_studio to align with the method's change. Task-4812554
Swiss payroll declarations now show which employee details are missing before users send or print them. This helps payroll teams identify and correct issues more easily, reducing confusion and failed or incomplete declarations.
Original PR description
It is currently complicated for non trained users to figure out what is missing before sending or printing a declaration. In this PR we extend the warning mechanism to declarations to visualize what information is missing on what employees. Forward-Port-Of: odoo/enterprise#86195
When portal users contribute Excel files that are converted into Odoo spreadsheets, their access is now safely adjusted to view-only. This prevents conversion errors caused by unsupported edit access for portal users, making the document workflow smoother for internal teams.
Original PR description
Let's say a Document Folder is shared with a portal user with 'edit' access. The portal user shares a .xlsx file to the folder, and an internal user later try to convert the file to odoo spreadsheet.…
Let's say a Document Folder is shared with a portal user with 'edit' access. The portal user shares a .xlsx file to the folder, and an internal user later try to convert the file to odoo spreadsheet. During the conversion, the portal user has 'edit' role on the folder, which is copied to the documents.access records of the converted sheet. Since Odoo prevents Spreadsheets from being shared in edit mode to portal users, _check_spreadsheet() raises a Validation Error. <img width="702" height="527" alt="image" src="https://github.com/user-attachments/assets/efee9a8b-161f-4def-9597-cf03ac4c54e3" /> To improve the user experience, this commit overrides `copy_data` of `documents.access` model to assign `view` access to portal users for an odoo spreadsheet. Maybe we can extract the if-conditions, and make it an API to reduce repeated code, as the same logic is being used in `_check_spreadsheet()` on the same file. However, looping through the copied vals_list only when handler is spreadsheet might have more value in terms of performance. opw-4753670
Internal users can now see the Documents app button, making it easier to access shared documents directly. This also clarifies that users do not need the full Documents User role to access documents shared with all internal users.
Original PR description
The app is accessible to all internal users via smart buttons and their portal already, showing the button is helpful in two ways: 1/ Easier access to the app, duh. 2/ Makes it explicit that you don't need to be a "Documents User" to have access to documents shared with all **internal users**, even those that are not documents user (that didn't have the app button available). In 18.0 so that new installations have it. Task-4889053
Field service users can once again access the map view for outgoing deliveries. This restores a useful planning view that was temporarily unavailable due to a dependency between community and enterprise features.
Original PR description
This commit is the continuity of the fix made in community. The issue fixed in community was the map view cannot be defined in the view mode of an action since the map view only exists in enterprise. This commit overrides the method defined in community to add the map view as before. Related PR: odoo/odoo#222003
The electronic signature reminder process now handles requests that do not have a validity date. This prevents scheduled reminder jobs from crashing and helps ensure signature follow-ups continue reliably.
Original PR description
The cron can fetch record with no validity date,
so the check request.validity < today
raise
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-18.3/odoo/tools/safe_eval.py", line 397, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "ir.actions.server(5136,)", line 3, in <module>
File "/home/odoo/src/enterprise/saas-18.3/sign/models/sign_request.py", line 437, in _cron_reminder
if request.validity < today:
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'bool' and 'datetime.date'
```
Forward-Port-Of: odoo/enterprise#90279The Swedish SIE4 import now skips accounting entries that contain no transaction lines. This prevents empty or invalid journal entries from being created, improving data quality during imports.
Original PR description
The aim of this commit is making sure that we don't import move without transaction in it. In SIE4, we can have moves with BTRANS and RTRANS tags that we are ignoring. It means that we could have move without any move lines. It's not an expected behavior in Odoo. This commit checks that the move data are created only if we have lines for that move. no task id Forward-Port-Of: odoo/enterprise#91783
Documentation and clarification updates
This pull request records that contributor nikhilnakrani99 has signed Odoo's Contributor License Agreement. This supports legal compliance for accepting their contributions and has no direct impact on product features or users.
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
Miscellaneous changes
Issue ----- In a SO, changing the quantity for a product with packagings through the catalog correctly updates the SOL's packaging but not the move's. Instead, it creates a new move for the difference in quantity (with the correct new packaging) while leaving the existing one unchanged. The user ends up with 2 moves with different packagings. Steps to reproduce ----- - Install both Sale and Stock - Enable "Product Packagings" under Settings > Sales - Create a new product with a custom
Original PR description
Issue ----- In a SO, changing the quantity for a product with packagings through the catalog correctly updates the SOL's packaging but not the move's. Instead, it creates a new move for the…
Issue
-----
In a SO, changing the quantity for a product with packagings through the catalog correctly updates the SOL's packaging but not the move's. Instead, it creates a new move for the difference in quantity (with the correct new packaging) while
leaving the existing one unchanged. The user ends up with 2 moves with different packagings.
Steps to reproduce
-----
- Install both Sale and Stock
- Enable "Product Packagings" under Settings > Sales
- Create a new product with a custom packaging for 2 units (inventory tab)
- Create a SO
- Add the product to the SO
- Confirm SO
- Open product catalog
- Update the product quantity to 4
- Go back to the SO
- Go to the linked delivery
-> The delivery has 2 lines instead of 1
Cause
-----
The logic flow is different between when in form or catalog view.
When changing the quantity of a sale line through the form, the quantity update is done on a temporary record. This triggers a change of the packaging through
https://github.com/odoo/odoo/blob/0a0dc2f1bd54f44356a5959b8bcd52aaddcf1261/addons/sale/models/sale_order_line.py#L649-L650
When saving the changes, both the quantity and packaging are present in the write `values` as both fields have to be updated on the real record. This allows to enter the following block, which updates the packaging on the existing move.
https://github.com/odoo/odoo/blob/0a0dc2f1bd54f44356a5959b8bcd52aaddcf1261/addons/sale_stock/models/sale_order_line.py#L198-L201
Later on in the write, we trigger a replenishment.
https://github.com/odoo/odoo/blob/0a0dc2f1bd54f44356a5959b8bcd52aaddcf1261/addons/sale_stock/models/sale_order_line.py#L205-L206
This replenishment creates a new move for the rdifference in quantities, using the SOL's new packaging. Since both the new and existing line have the same packaging, they are merged together. Everything works as expected.
When making changes through the catalog, we are directly writing the new quantity on the existing SOL. We directly enter the SOL's `write` method with only the new quantity in `values`.
This means we don't update the packaging on the existing move since `product_packaging_id` is not in `values` so we can't enter the block
https://github.com/odoo/odoo/blob/0a0dc2f1bd54f44356a5959b8bcd52aaddcf1261/addons/sale_stock/models/sale_order_line.py#L198-L201
The write then goes on to trigger a replenishment. When preparing to create the procurement, we access the SOL's `product_packaging_id`
https://github.com/odoo/odoo/blob/0a0dc2f1bd54f44356a5959b8bcd52aaddcf1261/addons/sale_stock/models/sale_order_line.py#L248
Since it's dependency (the quantity) changed, the compute is triggered. The SOL packaging is updated and the newly computed packaging is used to create the procurement (and subsequent move).
We end up with two moves with different packagings,
- the existing move with the old packaging
- the new move with the new (correct) packaging
They can not be merged together because their packagings differ -> bug.
Version constraint
-----
The bug is only present in 17.X versions, as packagings have been deprecated in 18.0.
Making the field computed
-----
We could make the move's packaging a *computed* field. This seems like the most logical and practical solution. However, this approach has some problems:
- the field is used for both sales and purchases so we'd have to adapt the behaviour there as well.
- we have to consider multi step routes. In such cases, the moves are linked between themselves but not to the SOL. This means we can't make the dependence be on the SOL packaging, we have to make it on the other move's. So we would have to make the field recursive, so that an update on the first move's packaging can propagate along the chain.
- adding onto the previous point, sale and purchase multi step routes use different rules, so we would depend on the origin's product_packaging_id in one and on the destintation's in the other.
This leads to us propagating changes both ways across move chains, so we don't know whether the origin or the destination has the correct packaging.
Solution
-----
Update the packaging of existing moves through the SOL's write method before it launches the replenishment.
Why this works
-----
We first store the existing packaging (or lack thereof) of the SOL
> old_packaging = {sol: sol.product_packaging_id for sol in self}
We then write the content of `values` on the record.
> res = super(SaleOrderLine, self).write(values)
This only updates the quantity of the SOL.
We then force the recomputation of the SOL's packaging
> if sol.product_packaging_id != old_packaging[sol]:
If the new packaging differs from the previous, we update the existing move(s) so that they use the new packaging of the line
> sol.move_ids.filtered(
> lambda m: m.state not in ['cancel', 'done']
> ).product_packaging_id = sol.product_packaging_id
Only then does the write launch the replenishment
> lines._action_launch_stock_rule(previous_product_uom_qty)
Since the existing moves' packaging has been updated, they will correctly be merged with the new ones.
-----
Ticket:
opw-4603600
Forward-Port-Of: odoo/odoo#206973Modifications are made around read, filtered, list comprehension. The read function usually does not prefetech fields other than stated. But in this case, since the fields are related fields from another model, The fields of the other model are prefeteched. This includes the body which can be very big in size and cause an out of memory error. Filtered does not need other fields and keeps them unnecessarily in cache. List comprehension where it has a reference to specific field inside th
Original PR description
Modifications are made around read, filtered, list comprehension. The read function usually does not prefetech fields other than stated. But in this case, since the fields are related fields from…
Modifications are made around read, filtered, list comprehension. The read function usually does not prefetech fields other than stated. But in this case, since the fields are related fields from another model, The fields of the other model are prefeteched. This includes the body which can be very big in size and cause an out of memory error. Filtered does not need other fields and keeps them unnecessarily in cache. List comprehension where it has a reference to specific field inside the model also triggers the prefetecher. Benchmark: | |Number of queries| SQL time| Python time|| |-------|----------------------------|----------------|---------------|-| |with prefetch| 82| 1.887 | 7.898| Out of memory| |Without prefetch| 120| 0.385 | 5.973| | The benchmark with the prefetch was done locally with increasing the memory limit. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#206125 Forward-Port-Of: odoo/odoo#183893