Daily updates from Odoo
Navigate
Branch
Tuesday, August 12, 2025
84 changes
47 changes
New functionality added to Odoo
Adds a backend salary calculator so HR teams can simulate gross-to-net salary offers directly in Odoo. The change also makes salary offers more flexible by allowing them to use employee or company defaults when no contract template is selected.
Original PR description
task-4569214
Enhancements to existing features
People signing documents through a public link can now see and move to their next pending documents after completing a signature. This makes the signing flow smoother for external partners and reduces missed follow-up documents.
Original PR description
Before this commit, when signing the SENT requests through a link (not logged in Odoo), the next documents to be signed by that partner were not shown. After this commit, the unlogged partner can now go to the next documents after completing the signature of any SENT request received. Co-authored-by: Arnaud Joset <arj@odoo.com> task-4859714
Signature requests created from business records can now reuse an existing signing template while replacing its PDF with an attachment from that specific record. This makes it easier to prepare accurate documents for signing without creating separate static templates for each record.
Original PR description
Before this commit, it was possible to link sign request to records (inheriting mail.thread) but the sign.template were static. This commit allows to copy an existing sign.template and adapt the PDF to one of the attachment of the record. taskid: 4270142
Mobile users now get a dedicated Inbox entry in Discuss and the messaging menu, making mailbox access clearer and faster. Message and composer quick actions are also more consistent across related apps, improving usability in conversations and support workflows.
Original PR description
1. mobile discuss app and messaging menu now has dedicated "Inbox" item _- messaging menu in mobile has to display discuss for mailboxes, therefore the "content" part of Discuss namely `DiscussContent` has been moved into its own component_ 2. message and composer quick actions now use `ActionList` _- action definition and style slightly tweaked_ 3. Discuss action definitions now has typedefs _- registering action is made through `registerXAction()` function, where `X` is thread/message/composer_ 4. `ActionList` component props simplified to `actions` (from `quick`, `other`, `partition`) _- can pass either list of actions (single group) or list of list of actions (actions are visually split in groups)._
Users can now update project budgets while they are still in draft state, including adding new budget lines. This makes budget preparation more flexible and reduces the need to recreate budgets when early details change.
Original PR description
Currently, once the user has created the budget, they are unable to edit it or add new lines, even if the budget is in the draft state. In this commit, we have made it editable in the draft state for the user's convenience. task-4760387
Belgian payroll now excludes PFI contracts when calculating an employee's seniority for departure notice periods. This helps ensure notice periods are generated according to Belgian rules and avoids overstating seniority for affected employees.
Original PR description
When you generate the notice period for leaving employees, you must compute their seniority. In Belgium, PFI contracts should not be taken into account. This commit filters the contracts to ignore PFI ones. task-4788455 Forward-Port-Of: odoo/enterprise#91495 Forward-Port-Of: odoo/enterprise#90902
Helpdesk users can now create additional refunds for an invoice after earlier partial refunds have been paid or are in payment. This keeps invoices available for refunding until the total refunded amount reaches the original invoice total, reducing manual workarounds and supporting more accurate customer service flows.
Original PR description
Previously, users couldn't select an invoice for another refund if all of its credit notes were already paid or in payment — even if the invoice was only partially refunded. For example: If a user created a partial refund for the first time and marked it as paid, the original invoice could no longer be selected for any further refunds. Now, invoices remain available for refunds as long as the total refunded amount is less than the original invoice's amount_total. Task ID: 4582294
Payroll work entries are being simplified to track work duration directly instead of relying on separate start and stop dates. This should make payroll, attendance, leave, expense, and planning calculations more consistent and easier to maintain across related processes.
WhatsApp conversation membership now keeps the pinned status directly on each member record. This supports more reliable and efficient handling of pinned chats for users.
Original PR description
task-4851885 [Community PR](https://github.com/odoo/odoo/pull/217366)
The mobile Discuss navigation now includes an Inbox entry, making it easier for users to access incoming messages on smaller screens. Related updates ensure messaging, WhatsApp, live chat, and helpdesk interactions continue to work correctly with the navigation change.
Original PR description
Part of task-4967066
The VoIP app icon has been refreshed with a new design in both image formats used by Odoo. This keeps the app’s appearance aligned with the latest visual branding and improves recognition for users.
Original PR description
This PR updates the voip png and svg icon to the new one. task-4987745 | Before | After | |--------|--------| | <img width="331" height="334" alt="Screenshot 2025-08-07 at 16 30 15" src="https://github.com/user-attachments/assets/61c6c7eb-3c2c-4120-a713-b6f4a5fbf44f" /> | <img width="331" height="334" alt="Screenshot 2025-08-07 at 16 29 54" src="https://github.com/user-attachments/assets/cf1d9449-109b-4de9-a4c2-d3b80b84d1d8" /> | PR Com: https://github.com/odoo/odoo/pull/222175
Bank statement processing now finds matching partners in batches instead of repeating the same work for every statement line. This reduces database lookups and should make importing or reconciling large bank statements faster and smoother.
Original PR description
The retrieve_partner function is actually executed on each statement line, with multiple search, which is killing performance. This commit change that, so retrieve_partner is executed on a statement line recordset, minimizing the amount of queries on each call. task-4749377 Forward-Port-Of: odoo/enterprise#87444
The CRM pipeline dashboard chart titles were updated so they correctly match the data being shown. This helps users interpret carousel charts more easily and reduces confusion when reviewing sales pipeline insights.
Original PR description
This commit updates the titles of the new added carousel charts as their measure/group were inverted. Task-5008685
Businesses can now turn call transcription on or off separately for each VoIP provider instead of having it enabled everywhere when AI VoIP is installed. This helps organizations manage where call data may be transcribed and shared with external services, supporting regional compliance needs.
Original PR description
Until now (after ref.1) call transcription was globally enabled by default once the `ai_voip` module was installed. The only way to prevent transcriptions (and sending data to external entities) was to uninstall the module entirely. This commit introduces a new `transcription_policy` field on the `voip.provider`, allowing transcription to be explicitly disabled per provider. Since providers are typically tied to specific regions, this enhancement improves compliance control across geographies. Planned followup: --- Transcription policy selection field should be expanded with a "user" option, that will allow users to decide if they want their individual calls transcribed. References --- (ref.1) f96d1f4cc52c009a4f55cfaabf7b683bdf9e170d [ADD] ai_voip: end-to-end post-call recording & transcription Related ticket task-4532108
Certified Belgian point of sale setups now guide users to configure the required printer and fiscal data module instead of stopping with an error. When only one fiscal data module is available, the system selects it automatically, reducing setup friction and support needs.
Original PR description
If one wants to use a certified pos without FDM or without printer, open the configuration modal to ease the configuration instead of raising a UserError. If there is only one fdm available, the pos automatically selects this one.
The Documents sharing panel is now easier to use and supports sharing multiple documents at once. Users can also find shared documents more quickly with new search options and filters for shared links, media files, and URLs.
Original PR description
[IMP] documents{_hr|_spreadsheet}: improve share panel We convert the share panel in a wizard and improve it by allowing sharing multiple documents at once. Technical notes: - if we set partner_id…
[IMP] documents{_hr|_spreadsheet}: improve share panel
We convert the share panel in a wizard and improve it by allowing sharing multiple documents at once.
Technical notes:
- if we set partner_id and documents_share_id fields as required in documents_share_access, it doesn't work (ex.: wizard button not updated when deleting an access).
- if we set original_role as required in documents_share_access, it cause a validation error when updating the role when the wizard is saved (original_role is empty while it has been initialized with a value). We cannot set it readonly either (cause "format requires a mapping" error).
[IMP] documents: improve document search
We add a "shared with" in quick search to easily look for all documents/folders shared with a contact.
And we add the following filters:
- to display all files and folder in anyone with the link.
- to display only images and videos
- to display only URL
[IMP] documents: add an option to avoid propagate rights
As we want to avoid propagating rights when updating rights on files and folders at the same time. We add an option to avoid propagating rights on the method action_update_access_rights of documents.document.
Task-4848234Saudi payroll now includes updated salary rule calculations, annual leave setup, and employee/contract fields for common local costs such as Iqama, medical insurance, work permits, and exit re-entry. This helps businesses in Saudi Arabia calculate payroll obligations and leave-related compensation more accurately within one consolidated payroll structure.
Original PR description
- Added a new option in settings to set the "Annual Leave" time-off type. - Added new fields in `hr.contract` for: - Iqama Annual Amount - Medical Insurance Annual Amount - Work Permit Annual Amount…
- Added a new option in settings to set the "Annual Leave" time-off type. - Added new fields in `hr.contract` for: - Iqama Annual Amount - Medical Insurance Annual Amount - Work Permit Annual Amount - Added new fields in `hr.payslip` for: - Include Exit-Re-Entry - Exit Re-Entry Amount - Added Rule Parameters for: - Saudi GOSI Company Contribution - Non-Saudi GOSI Company Contribution - Saudi Arabia Overtime Rate - Added new field in `hr.employee` to calculate number of remaining annual leave days. - Merged "Saudi Employees Payroll Structure" and "Expat Employees Payroll Structure" into a single "Saudi Employees Payroll Structure" with updated salary rules. - Updated salary rules - Out of Contract Days - Sick Leave Calculation - Remaining leave days compensation - Company contributions for Medical Insurance, Iqama, and work permit - Exit re-entry - Annual Leave Provision - Unpaid Leave [Amendment] - Overtime Calculation task-4460705
Spreadsheet version history now keeps and shows the actual date each revision was originally made, even after a spreadsheet is duplicated. This helps users better understand when changes happened and trace spreadsheet evolution more reliably.
Original PR description
Currently, when duplicating a spreadsheet along with its revisions, each duplicated revision is assigned the `create_date` of the new record, resulting in all revision timestamps showing the exact same datetime. This prevents users from being able to trace the history of changes and makes it difficult to identify when a specific revision was originally made. To address this issue, a new field of `datetime` type `revision_date` is introduced to stores the actual datetime when the original revision occurred. The version history side panel now displays this `revision_date` field instead of relying on `create_date`, enabling users to accurately track the evolution of spreadsheet changes over time. NOTE: For the 'original data' revision and in order to avoid adding a new field on the spreadsheet model, the timestamp will be hidden. Task-[4854898](https://www.odoo.com/odoo/project/2328/tasks/4854898)
Payslip emails for Swiss payroll now only include a direct document link when the employee does not have a user account. This helps route employees with accounts through the standard access flow while still giving others a practical way to view their payslip.
Original PR description
- adapt the mail template to send the driect link only when the employee does not have a user Task: 4747003
When a salary offer is created, the company car is now selected automatically from the linked contract template when available. If the template has no car, the system uses the employee version’s car instead, reducing manual entry and avoiding missing car assignments.
Original PR description
In this PR, we fixed the assignation of the car in the contract when the contract template for the version has a company car. When creating an offer, automatically set the transportation car based on the linked contract template. If the contract template has no car, fall back to the car defined on the employee version. If neither has a car, leave the field empty. Related task: 4926053.
Payroll menus for versions and offers are now hidden unless debug mode is enabled, reducing clutter for everyday users. Payslip generation has also been improved to avoid creating duplicate payslips for the same person over the same dates, helping payroll teams produce cleaner and more reliable pay runs.
Original PR description
Reference task: https://www.odoo.com/odoo/project/1251/tasks/4988589 - Restricted visibility of "Versions" and "Offers" menu items to debug mode only. - Payslip generation logic filters out employee versions when same start/end date and state Task - 4988589
Bank reconciliation screens have been simplified by removing less-used dropdown navigation, hiding a mostly redundant status, and keeping account assignment easier to access. Attachments that are already inherited from statements are also no longer shown as extra paperclip indicators, reducing visual clutter for accounting users.
Original PR description
- Removing the action of going to the entry of statement line from the dropdown, new the only possibility will be from the list view - Hide the status of the statement line since it's mostly posted - Adding the set account button everytime next to the set partner task-4985155 Forward-Port-Of: odoo/enterprise#91423
Users are now discouraged from directly changing standard spreadsheet dashboards because those changes can be lost during upgrades. This helps business users make more informed edits and reduces the risk of unexpected dashboard changes after an update.
Resolved issues and error corrections
Australian payroll withholding amounts are now included in tax return closing entries, helping businesses produce more complete tax accounting records. The payroll accounting module will also install more reliably when Australian localization is set up, avoiding a setup issue for new Australian companies.
Original PR description
This PR is divided in 2 commits: A first commit is an implementation AU specific and will create the lines related to tax on salary in the tax return closing entry. Before this commit, these lines…
This PR is divided in 2 commits: A first commit is an implementation AU specific and will create the lines related to tax on salary in the tax return closing entry. Before this commit, these lines weren't taken into account in the closing entry. The condition to select the account.move.line are the following: - The journal item has a "W2", "W3" or "W4" (Withholding Tax) tax grid whose journal entry is linked to an hr.payslip. - The journal item does not have an originating tax record (i.e., tax_line_id is empty). - The journal item is posted to a tax provision account (i.e., a balance sheet one) as defined on the salary rule. A second commit fixes a bug: the manifest of the l10n_au_hr_payroll_account module was having a 'countries': ['au'] dependency, that was adding a condition to the dependencies to auto install the module: we expect an existing AU company in DB. But for example if the user installs l10n_au, the condition is evaluated at the moment he clicks on install, and no AU company exists at that time. Task-4921992 Forward-Port-Of: odoo/enterprise#91913 Forward-Port-Of: odoo/enterprise#90422
Rental quotation product selection now avoids showing products that are neither available for sale nor rentable. This prevents sales teams from accidentally adding unavailable products to customer quotations, improving quote accuracy.
Original PR description
Versions
--------
- saas-18.3
Steps
-----
1. Have a product that's neither salable not rentable;
2. open a quotation;
3. click "Add a product".
Issue
-----
It's possible to select the unsalable product.
Cause
-----
Commit d5f72c201bf0 added a `_domain_product_id` override to `sale_renting` which includes `('rent_ok', '=', order_is_rental)`. As a consequence, whenever you have a quotation that isn't a rental, this domain will retrieve *any* product that isn't rental either.
Solution
--------
Add a `('rent_ok', '=', True)` condition to ensure the override only affects rental orders, and that non-rental orders won't retrieve all non-rental products.
opw-4983348
Forward-Port-Of: odoo/enterprise#91701Automatic currency rate updates from the UAE Central Bank now include the Sudanese Pound. This ensures businesses using SDG receive current exchange rates without manual correction.
Original PR description
**Steps to reproduce**: 1. Install the `account` and `l10n_ae` modules. 2. Go to `Invoicing → Configuration → Currencies` and activate the `Sudanese Pound (SDG)` currency. 3. Navigate to `Settings → Invoicing → Currencies → Automatic Currency Rates`. 4. Select `[AE] Central Bank of the UAE` as the currency provider and manually fetch rates. <img width="463" height="181" alt="image" src="https://github.com/user-attachments/assets/31257e2e-8360-4cdb-877e-2ea41487ddea" /> 5. Return to the Currencies list. **Observed behavior**: - The rate for the `Sudanese Pound (SDG)` is not updated. **Root cause**: - The `SDG` currency is missing from the `MAP_CURRENCIES` dictionary, so the provider doesn't fetch its rate. **Solution**: - Add the missing `SDG` currency mapping to `MAP_CURRENCIES`. opw-4869204 Forward-Port-Of: odoo/enterprise#91790
Fixed an issue in the Belgian point-of-sale fiscal integration where printing a bill again for an already-synced order could fail silently. Businesses can now reprint or issue multiple bills for the same order consistently, even when no new order changes need syncing.
Original PR description
Before this commit an issue was appearing when we try to make multiple bill on the same order. If the order was already synced and didn't get any changes, clicking `Print bill` with `pos_blackbox_be` wouldn't do anything. Now we print the bill after syncing the order, even if the order don't have any new changes to sync. task-id: 4901299 community PR: https://github.com/odoo/odoo/pull/222424 Forward-Port-Of: odoo/enterprise#92070
Worksheet fields created during onboarding are now properly included in translation exports. This helps field service and quality teams use localized worksheet labels reliably across languages and updates.
Original PR description
_*=industry_fsm_report, quality_control_worksheet Issue: - In the `industry_fsm_report` and `quality_control_worksheet` modules, worksheet fields created during onboarding were not translatable and were missing from the exported .po files. Cause: - Field creation was moved from XML to Python (see https://github.com/odoo/enterprise/commit/d619aa4d0d042be3f899b777081b7fb90f851c84). As a result, the fields were no longer automatically registered in `ir.model.data`, preventing the translation system from detecting them. Solution: - Set the `_import_current_module` context and added explicit IDs when creating fields in python. This registers the fields in `ir.model.data`, enabling translations and keeping field references stable across updates. task-4585020
The Spanish VAT record book export now recognizes the 0.26% and 1% equivalence surcharge purchase taxes. This prevents an error when exporting VAT books for invoices using these rates, helping Spanish companies complete tax reporting reliably.
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 Forward-Port-Of: odoo/enterprise#92116
Spanish Model 349 reports now calculate rectified amounts using linked credit notes only, instead of being affected by payments or other unrelated transactions. This ensures rectification figures and official BOE exports reflect the correct tax position for prior-period supplier bills.
Original PR description
# How to reproduce the issue With l10n_es fiscal position: - Create a bill in a previous period (e.g., amount 1000). Partially credit note this bill for 500. - Register a partial payment of 250 on…
# How to reproduce the issue With l10n_es fiscal position: - Create a bill in a previous period (e.g., amount 1000). Partially credit note this bill for 500. - Register a partial payment of 250 on this bill. - In the tax report, go to model 349. Under the Rectificationes section, the new rectified value will be 250. This is incorrect, as the rectifications in this report should only reflect the value of the original move from a past period after applying the credit note. Payments or other transactions should not impact this report. This commit adjusts the computation of the report (and the BOE export) to ensure that, instead of using `amount_residual` (which includes payments and other transactions), the report uses the sum of the credit notes linked to the move included in the rectification report. Also changed the test test_mod349_credit_note. The rectification section is supposed to show the adjusted amount after rectification. In the test a bill of 400 is fully refunded. Instead of 400, the report should show 0. (https://www.boe.es/buscar/doc.php?id=BOE-A-2010-5098 in TIPO DE REGISTRO 2: REGISTRO DE RECTIFICACIONES. in 153-165 Numérico Base Imponible Rectificada section) opw-4895636 Forward-Port-Of: odoo/enterprise#91350 Forward-Port-Of: odoo/enterprise#89431
UPS Commercial Invoices now use the currency from the related sale order instead of the company’s default currency. This prevents incorrect customs paperwork when shipments are based on orders in foreign currencies.
Original PR description
The automatically generated UPS Commercial Invoice is using the company's currency instead of the currency of the invoiced order. ### How to reproduce: * Setup UPS Delivery Method. * Create a sale order with a currency different from the company's. * Assign a customer in a different country. * Validate the delivery. * Check the UPS Commercial Invoice — it shows the company's currency. opw-4973217 Forward-Port-Of: odoo/enterprise#92065 Forward-Port-Of: odoo/enterprise#91883
This fix ensures the U.S. payroll leave type screen includes the expected fields by loading the missing view configuration. It also corrects a label so users see clearer information when managing leave types.
Original PR description
Before this commit, the modification of the leave type views was not introduced in the manifest, resulting in the fields being absent from the view. This commit corrects the label as well as introduces that view in the manifest Forward-Port-Of: odoo/enterprise#87423
This change fixes an error that could appear after a user successfully signed a document with Aadhaar and returned to Odoo. It ensures the signing request is referenced correctly, allowing the completed signing flow to continue without interruption.
Original PR description
Before this commit, after successfully signing with Aadhaar and returning to Odoo, `sign_request = request_item_sudo.sign_request_id UnboundLocalError: local variable 'request_item_sudo' referenced before assignment` This happened because request_item_sudo was not defined. This commit fixes the issue by correcting the variable name so it’s properly defined before use.
The VoIP softphone now checks whether the user is typing in another editable field before taking focus back after a call. This prevents interruptions and reduces the chance of accidentally entering text in the wrong place.
Original PR description
Before switching the focus back to the softphone after a call, make sure the user isn't typing somewhere else. Only autofocus if the focus is not on an editable element. Task-4997513. Forward-Port-Of: odoo/enterprise#91970 Forward-Port-Of: odoo/enterprise#89562
This fix restores refund information needed by Italian fiscal printers when processing point-of-sale refunds. It prevents printers from blocking refund receipts, helping stores complete refund transactions reliably.
Original PR description
The refund are bugged after PR #89419 . That PR removed the header but in the header are passed the refund information needed by italian fiscal printer to print the refund. Without this PR the fiscal printer is blocking. The printRecMessage on the receipt is required before the beginfiscalreceipt Forward-Port-Of: odoo/enterprise#91042 Forward-Port-Of: odoo/enterprise#91007
The salary configurator now displays dropdowns and the personal information section more consistently across screen sizes. This makes the form easier to read and use for employees configuring their salary package.
Original PR description
this commit fixes dropdown styling in the salary configurator. moreover, `your personal information` section is fixed so that the background color covers the entire width of the screen in different screen sizes. task-4953595
Rental orders now show the correct remaining stock even when the Rental Transfer setting is turned off. This prevents available rental products from being incorrectly marked as unavailable after another rental has been picked up.
Original PR description
Steps to reproduce: - Do not enable “Rental Transfer” in settings - Create a storable product “P1”: - Enable “Can be rented” - update available quantity to 10 units - Create a first rental order for…
Steps to reproduce:
- Do not enable “Rental Transfer” in settings
- Create a storable product “P1”:
- Enable “Can be rented”
- update available quantity to 10 units
- Create a first rental order for 24h:
- 9 units of P1
- Confirm the order
- Create a second rental order for the same 24h period:
- 1 unit of P1
-> Expected: The availability widget is green and indicates 1 unit available (correct).
Problem:
After picking up the first order, the widget on the second order turns red and incorrectly shows no availability.
The current logic checks virtual_available (1 unit) and subtracts rented_qty_during_period (9 units), resulting in -8. It then takes max(0, -8) → 0. However, the actual picked quantity should be taken into account, regardless of whether “Rental Transfer” is enabled, since disabling it merely omits the creation of a picking—not the move itself.
opw-4901017
opw-4906162
Forward-Port-Of: odoo/enterprise#92056
Forward-Port-Of: odoo/enterprise#91155Approval requests now prevent the same person from being added more than once as an approver. This avoids traceback errors in the Approvals app and removes duplicate demo data that could trigger the issue.
Original PR description
#### Reproduce Approvals app -> My Approvals -> My Requests (Traceback Error) #### Issue The demo data contains a duplicate record for an approver (the user is set as default approver for the approval category and added again as record in xml data), so the request had 2 approvers with the same user. #### Fix replaced the `@api.constrains` with a UNIQUE SQL constraint to enforce the check of same user linked to more than one approver for single request, and deleted duplicate record from demo xml data. task-4984137
Exported audit reports will now include the .pdf file extension in their names. This helps Windows recognize the files as PDFs so users can open them directly with their PDF viewer without manual renaming.
Original PR description
Currently, when a user exports an audit report, the server returns a download URL. During the download, the server sets the `Content-Type` HTTP header to `application/pdf`, indicating that the file is a PDF. However, for Windows users, setting the `Content-Type` header alone is not enough. The operating system may treat the file as a generic file, which means it won't automatically open in a PDF viewer when double-clicked. Instead, the user must manually assign the `.pdf` extension or choose a PDF reader to open it. To resolve this, we will include the `.pdf` extension in the file name. This ensures that the operating system correctly identifies the file as a PDF and opens it with the appropriate application. Task-4989809
Field service teams can once again use the map view when opening outgoing stock deliveries. This restores a helpful visual planning option that was temporarily missing due to a technical split between Odoo 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 Forward-Port-Of: odoo/enterprise#92032
The Spanish VAT books export now avoids a crash when the company's IAE Group or Heading is missing. Instead, users are redirected to the company settings to complete the required setup, making the issue easier to resolve.
Original PR description
**Steps to reproduce:** 1. Install the `l10n_es_reports` module. 2. Remove the value from the `IAE Group or Heading` field in company settings. 3. Navigate to `Accounting -> Reporting -> Tax Report -> Generic Tax Report`. 4. Click the down arrow and select `VAT Record Books (XLSX)`. **Observed behavior:** * A traceback error occurs when attempting to export the VAT books. **Root cause:** * The system attempts to traverse the `IAE Group or Heading` field, which is empty, causing the traceback. **ref**: https://github.com/odoo/enterprise/blob/d8539dff5f3dcecfeb99fd7fc22a6915aaa02c4b/l10n_es_reports/models/libros_export.py#L126-L138 **Solution:** * If field `IAE Group or Heading` not configured, a RedirectWarning is raised to guide the user to the company form view for proper setup. opw-4981531 Forward-Port-Of: odoo/enterprise#92122 Forward-Port-Of: odoo/enterprise#91607
Adjusted accounting report tests so they respect new validation rules for externally calculated report lines. This prevents false test failures in complex tax reports, such as Luxembourg tax annexes, while keeping report behavior aligned with stricter safeguards.
Original PR description
The corresponding community PR (https://github.com/odoo/odoo/pull/221407) contains a fix that requires the _validate_engine constraint to reject any groupby value for the 'external' engine. Therefore, it is now needed that the test ensuring non-stored related fields can be used in groupby is adapted in order to also exclude those expressions when changing the groupby value of the lines using a custom engine on any of their expressions. Without that, complex reports like the annexes of the Luxembourgese tax report fail the test. Forward-Port-Of: odoo/enterprise#92096
This update adds the required AI VoIP dependency to the enterprise discussion test module. It prevents test failures when transcription-related VoIP settings are expected but the supporting module is not available.
Original PR description
After (ref.1) test suite includes `voip.provider.transcription_policy` in its expected values in the store (ref.2).
Since `transcription_policy`` is coming from ai_voip module, and there is no direct dependency, it can cause issues when ai_voip isn't there.
This commit prevents that situation by introducing the dependency.
Refs:
---
(1) [IMP] ai_voip: introduce per-provider transcription setting
df402bcdd9023157ee3661e453002bacb421384c
(2) mail.tools.discuss.Store (voipConfig wiring)
related task
task-4532108Features or functions removed from Odoo
Several website-related apps have had obsolete snippet configuration code removed after a prior website refactor made it unused. This is an internal cleanup that reduces maintenance overhead and should not change day-to-day website behavior for users.
Original PR description
* : website_appointment, website_helpdesk, website_knowledge, website_sale_renting, website_sale_subscription, website_studio Following the website refactor [1], that code is not used anymore. [1]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2
An unused shortcut in the Attendance Gantt view was removed because it was no longer referenced. This keeps the system configuration cleaner with no expected change for day-to-day users.
Original PR description
Remove unused action 'hr_attendance_gantt.action_open_gantt_create_view_form' since it is unused Task ID: 4988707
The legacy payroll report has been removed because it caused severe performance issues. Payroll dashboards and related views now rely on newer payslip line and workday line reports, improving reliability for payroll analysis.
Original PR description
- As we created Payslip line and Payslip Workdays Lines reports, it is time for this report to go as it disastrous performance issues Task: 4624182
Code cleanup and technical improvements
The Italian EDI withholding reporting functionality has been folded into its parent Italian EDI module, removing the need for a separate backport-specific module. This simplifies maintenance and keeps the same functionality available from the main localization package.
Original PR description
This commit integrates the functionality from the `l10n_it_edi_withholding` module into its parent, `l10n_it_edi`. The separate module was originally created to backport this feature to a stable version (16.0), making it obsolete now. Original commit: https://github.com/odoo/odoo/commit/90f9f9f23478bd54625c152c7f5ab2d0c18e3780 See odoo/odoo#221365 See odoo/upgrade#8147 Task [link](https://www.odoo.com/odoo/project/967/tasks/4988044) task-4988044
37 changes
Enhancements to existing features
Users can now update only part of the analytic distribution when editing multiple journal items or analytic items at once. This makes bulk accounting updates more practical and reduces repetitive manual corrections.
Original PR description
In Journal Items list view, mass edition of the Analytic Distribution on several records is disappointing and reported almost unusable. It is impossible to mass edit only one plan on multiple lines using a distribution. This commit is adding the possibility to do so from the list view of analytic items but also from the journal items. task-4937143
This update adds a warning when sending Mexican electronic invoices for customers missing required country or ZIP information while the public CFDI option is turned off. It helps users catch incomplete customer data before invoice sending, reducing compliance issues and failed submissions.
Original PR description
Adding a warning and a check to account.move.send constraints for trying to send an invoice for a customer that doesn't have either country or ZIP specified, when 'CFDI to Public' is set to False (requires user action to override default behavior). task-4963869
The UAE payroll end of service report now calculates an employee’s worked years based on their full duration with the company, rather than only actual worked days. This provides a more accurate tenure figure for end of service reporting and related HR payroll processes.
Original PR description
- update the calculation for the worked years in the end of service report to return the whole duration worked with the comapny not just the actual worked days. Task: 4703337
Resolved issues and error corrections
Odoo now shows a clear user-facing error when a document numbering prefix or suffix contains an invalid placeholder. This prevents confusing system errors when creating records such as sales orders and helps users correct the sequence setup more easily.
Original PR description
Currently, an error is raised when a sequence is generated with an invalid legend in the prefix or suffix. **Steps to reproduce:** - Install Sales module. - Update the sale order sequence prefix to S%(days)s. - Create a new sale order. **Error:** `KeyError - 'days'` **Cause:** An error occurs when the user provides an invalid suffix in `ir_sequence` and the system tries to generate that sequence at [1]. [1] - https://github.com/odoo/odoo/blob/18da9b6dfc9dc376700cd948a09ae201bf897990/odoo/addons/base/models/ir_sequence.py#L235-L236 **Fix:** To resolve the issue, raise a user error for an invalid sequence. **Ref:** https://github.com/odoo/odoo/commit/18cac1caa21149d70009aa50f3e90dfbc18456a3 Sentry - 6684586181 Forward-Port-Of: odoo/odoo#217142
This fixes a timing issue in an automated point of sale sales test by ensuring quantity changes entered through the numpad are fully applied before the test continues. The change helps keep quality checks stable and reduces false test failures during development.
Original PR description
Wait for the quantity update to take effect when updating with numpad. runbot-230078
This fix ensures that when a manufacturing order is unbuilt, returned components keep their original consignment owner information. This prevents consigned stock from being incorrectly mixed into company-owned inventory, improving inventory accuracy for manufacturing operations.
Original PR description
**Problem:** when a MO is unbuild, if some components where consigned, they will come back in stock as not consigned **Steps to reproduce:** - enable "consignemnet" setting - create a storable…
**Problem:** when a MO is unbuild, if some components where consigned, they will come back in stock as not consigned **Steps to reproduce:** - enable "consignemnet" setting - create a storable product (the comp) - set on on hand quantity of 3 without owner - set on on hand quantity of 4 with an owner - create another product (the final product), with a BOM of 7 of the comp product - create a manufacturing order for the final product, confirm and produce all. - unbuild it - open the comp product form, click on the on hand smart button **Current behavior:** - there is a quantity of 7 unconsigned **Expected behavior:** - there should be a quantity of 3 unconsigned and a quantity of 4 consigned **Cause of the issue:** when the stock move line is create in action_unbuild() there is no mechanism to get back the owner of the original stock move line from the MO https://github.com/odoo/odoo/blob/ceccb92af19a6a3fc0c7b5924d9f497b1aec1d55/addons/mrp/models/mrp_unbuild.py#L204 opw-4900386 Forward-Port-Of: odoo/odoo#219905
This update fixes an unstable automated test in the HTML editor area by ensuring the dropdown is handled consistently. It helps reduce false failures in Odoo's test pipeline, making validation runs more dependable without changing user-facing behavior.
Original PR description
The input dropdown is a popover and is therefore affected by [1]. Because of that, we cannot simply use `contains` without awaiting properly as it can easily break non-deterministically on the runbot. [1]: https://github.com/odoo/odoo/pull/211426/commits/54da715df84789f9a1acc0cfc91be41dcdbab140
This fix prevents Odoo from crashing when users open an app while multiple modules are still being installed. It makes the web interface handle partially loaded view information safely, improving reliability during installation workflows.
Original PR description
Currently, an error occurs when the user tries to install multiple modules and, during installation user tries to access any app. This issue happens because line [1] tries to get view info by view…
Currently, an error occurs when the user tries to install multiple modules and, during installation user tries to access any app. This issue happens because line [1] tries to get view info by view name, like `hierarchy`. Normally, we get the view information from the `_get_view_info` method (see [2]), and we override this method to add another view to the returned data (as in [3]). But during installation, when the user tries to access any app, the view is already loaded into the database. So when the `fields_get` method is called, the view is found. However, since the module isn't fully loaded yet, the overridden `get_view_info` method hasn't taken effect. As a result, the additional view we expect isn’t included, and accessing that view key causes an error. This commit fixes the above error by ensuring that `_view_info` is accessed only when `type_` is present in `_view_info` at [1]. [1]: https://github.com/odoo/odoo/blob/80976e3579db4862c16cafab2ec183a7a0d0b63c/addons/web/models/ir_ui_view.py#L14 [2]: https://github.com/odoo/odoo/blob/80976e3579db4862c16cafab2ec183a7a0d0b63c/addons/web/models/ir_ui_view.py#L22-L31 [3]: https://github.com/odoo/odoo/blob/80976e3579db4862c16cafab2ec183a7a0d0b63c/addons/web_hierarchy/models/ir_ui_view.py#L56-L57 sentry-5661154820
This fix prevents upgrade failures when one module changes a field to use company-specific values while another module is being updated. It helps ensure upgrades complete reliably without unwanted database type conversion errors.
Original PR description
before this commit: if module_A has a field ``company_dependent=False`` and module_B override it to ``company_dependent=True`` When -u module_A, there would be an error since ORM tries to convert column type of the field from varchar/integer/boolean... to jsonb This commit will add a patch to the field in the ORM registry if the field was company dependent before upgrade. 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
Attachments added while scheduling an activity are now linked to the final activity record instead of the temporary scheduling wizard. This prevents those files from being removed during future database upgrades, helping users retain important activity-related documents.
Original PR description
Steps to reproduce the issue: 1. Create a new activity on any `mail.thread` (`project.project` for example) 2. On the wizard, upload an attachment 3. Schedule the activity 4. Upgrade the database to…
Steps to reproduce the issue: 1. Create a new activity on any `mail.thread` (`project.project` for example) 2. On the wizard, upload an attachment 3. Schedule the activity 4. Upgrade the database to any future version Current behavior before PR: The attachments created with activities would be deleted due to the query [here](https://github.com/odoo/upgrade/blob/master/migrations/base/0.0.0/pre-clean-transients.py#L69), because they are linked to the transient model `mail.activity.scheduel`. Attachments linked to these models are deleted during the upgrade. Desired behavior after PR is merged: The newly created attachments are linked to the `mail.activity` record directly, avoiding the post-upgrade issue. This change also aligns the feature with attaching a file to a `mail.message` record, where the `res_model` and `res_id` fields move from `mail.compose.message` to the target model after posting the message. opw-4812659 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The point of sale product screen now adjusts the number of product tiles per row on mobile devices instead of forcing a fixed layout. This prevents the product list from overflowing and makes mobile checkout browsing smoother, with a test added to help avoid regressions.
Original PR description
- This commit fixes the issue of vertical scrolling on mobile devices, now we responsively display the correct number of product lists by line, instead of forcing the display of 3 per lines. - Also add a test to ensure that the product list does not overflow on mobile devices. backport of commit (8dba5b2781d40c0817829ce330aeea2c6b0bff36) task-id: 4922341 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Calendar reminders now only appear for upcoming events within the correct reminder window. This prevents users from receiving confusing notifications for meetings that have already passed, especially for recurring events.
Original PR description
Steps to reproduce the issue: 1. Create a calendar event (meeting, for example) 2. Set the start date as yesterday and in 30 minutes from now. 3. Set it to be recurrent every week with end_type set to end_date and in the future(1 month from now). 4. Add a reminder to the event (30 mins, for example) and ensure that calendar_last_notif_ack is set before the alarm window for your user's res.partner. 5. Save the event and observe an alarm notification made for an event in the past. After the fix, the calendar alarms will only trigger for events in the future and in their designated time windows. The recurrence logic was also removed from the query to align with this [[REF]](https://github.com/odoo/odoo/pull/42031/commits/a27afdb5434166c3ea48c18ccfba9e8245d18e62) since recurring events are all persistent records in the database. opw-4776638 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222214
Customer invoice lists can now be sorted using the Status and Sent columns. This makes it easier for accounting users to organize invoices and quickly find records based on payment or delivery status.
Original PR description
**Issue** Users were unable to sort invoices by the "Status" and "Sent" columns in the customer invoices list view. **Steps to Reproduce** 1. Go to Accounting > Customers > Invoices 2. Try sorting by the "Status" or "Sent" columns 3. Observe that sorting is not functional for these fields **Root Cause** Both `status_in_payment` and `move_sent_values` are computed (non-stored) fields. Odoo cannot sort by non-stored fields unless a SQL representation is provided using the `_field_to_sql` method. Opw-4976838 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures work entries for employees on flexible schedules use the actual time period being processed, rather than assuming a full standard day. This prevents incorrect 8-hour durations when attendances occur on public holidays or partial-day gaps, improving payroll and attendance accuracy.
Original PR description
### Steps to reproduce: - Set Marc Demo's contract work entry source to attendances and working schedule to flexible hours. - Create a public holiday with generic time off work entry type. - Create…
### Steps to reproduce: - Set Marc Demo's contract work entry source to attendances and working schedule to flexible hours. - Create a public holiday with generic time off work entry type. - Create one or multiple attendances for marc demo on the public holiday. - Regenerate work entries for marc demo for that day, the gaps in between the attendances created and the working hours will be filled with work entries with the right start/end time but duration will always be 8h. ### Cause: This is happening because when getting the duration batch for the work entry we get the attendance intervals the employee should work in that period and if the employee is flexible we will get a fake attendance with the number of hours required per day ignoring if the period is just a small period of the day ### Fix: We are checking now since the start date not monday so we don't set a fixed week start. We check if the period is less than the remaining hours we get it as it mostly means that it is less than one day opw-4887933
This fixes an intermittent automated test failure in Point of Sale when checking barcode searches for product variants. The change makes the test wait for the right product state, reducing false failures in validation runs without changing customer-facing behavior.
Original PR description
This fixes a random runbot failure in the barcode search test involving product variants. The issue was caused by timing problems when selecting a second variant of a product with the same template…
This fixes a random runbot failure in the barcode
search test involving product variants.
The issue was caused by timing problems when selecting a second variant of a product with the same template name. Due to UI delays, the wrong variant could be selected.
The issue happened in this sequence:
- The test searched the first barcode (12341357), which correctly
displayed the product template "Product with Attributes" with the
variant (Value 1, 3, 5, 7) preselected.
- The product was added successfully.
- Then the second barcode (12342468) was searched. But before the UI
had time to update
and reflect the new variant (Value 2, 4, 6, 8), the test clicked
again on the same product template — which still had the *first*
variant preselected.
- As a result, the first variant was added twice, and the expected
second variant was missing.
To prevent this, a distinct product template ("Product without Attributes") was introduced between the two variant searches to give the UI enough time to refresh. The tour was also updated to properly wait for the correct product to appear and to avoid triggering the configurator on products without attributes.
runbot-230339This fix prevents the Spanish Modelo 111 tax report from crashing when opened after a reporting engine change. It removes an incompatible grouping setting so affected users can access the report normally.
Original PR description
Commit https://github.com/odoo/odoo/commit/97fe24cea74241a7820841a470994d3ebf9d8d38 changed the engine for some report line of Modelo 111. The new engine used, `external`, is not compatible with having a grouping value defined by the user (field `user_groupby`). Except that value does not get removed from the report lines. As a result, a traceback pops up whenever we try to access the report. Two previous commits aimed to sync that field with the `groupby` field (https://github.com/odoo/odoo/commit/a7d54c76aaee325449248fa698adb9e549c486ee), and update it if it was not compatible with the engine (https://github.com/odoo/odoo/commit/0d5bf820c3737ee3e4af54d1fb556b72d6c59c3d) but both only work with `aggregation` engine. This commit makes `_validate_engine()` account for `external` engine, as it was only checking for `aggregation` engine when validating `groupby` related fields. opw-4972212 opw-4971497 opw-4931269 opw-4949654 Forward-Port-Of: odoo/odoo#221021
This fixes an issue where older Saudi ZATCA Phase 1 invoice QR codes disappeared after the electronic invoicing module was installed. Businesses can now see the correct QR code for both Phase 1 and Phase 2 invoices, supporting compliant invoice reporting.
Original PR description
Phase 1 ZATCA QR codes disappear when l10n_sa_edi is installed, there is a check for document submission to display the QR code for Phase 2 which older Phase 1 invoices will not pass as it doesn't use edi. Description of the issue/feature this PR addresses: Phase 1 ZATCA QR Code disappears once l10n_sa_edi is installed Current behavior before PR: Always hide Phase 1 ZATCA QR Code Desired behaviour after PR is merged: Showing Phase 1 and Phase 2 ZATCA QR codes based on the invoice task-5005304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
PDF reports covering multiple records now fall back to generating each document separately when automatic splitting cannot determine the correct pages. This prevents missing or broken report files in cases where report templates or PDF generation tools produce inconsistent outlines, though large batches may take longer to process.
Original PR description
When generating PDF reports with multiple records, the system tries to split the concatenated PDF using outlines. However, in cases where the number of outlines doesn't match the number of records or…
When generating PDF reports with multiple records, the system tries to split the concatenated PDF using outlines. However, in cases where the number of outlines doesn't match the number of records or outlines are missing, it falls back to generating individual PDFs per record by recursively calling `_render_qweb_pdf_prepare_streams()` for each `res_id`.
This ensures that each record gets its corresponding PDF even if splitting the combined PDF is not possible due to template or wkhtmltopdf inconsistencies.
issue related: https://github.com/odoo/odoo/issues/202299
Current Behavior:
The _render_qweb_pdf_prepare_streams method does not correctly generate PDF streams under specific conditions, causing the PDF to not be properly split for each res_id. When these conditions are met, the generated streams are set to None, resulting in incorrect PDF processing.
The issue occurs when all the following conditions are true:
reader.numPages != len(res_ids_wo_stream)
len(res_ids_wo_stream) > 1 and set(res_ids_wo_stream) == set(html_ids_wo_none) is True
not has_valid_outlines is False
has_same_number_of_outlines and has_top_level_heading is False, since has_same_number_of_outlines is False
Expected Behavior:
The method should correctly assign a valid PDF stream to each res_id, ensuring proper document splitting even when outlines cannot be used.
Steps to Reproduce:
Generate a PDF report where the number of pages does not match the number of res_ids.
Ensure that the report includes multiple records, and the outlines structure is not valid for splitting.
Debug and Observe that the streams assigned to res_ids are None, leading to issues in PDF rendering.
Error:
Odoo Server Error
RPC_ERROR
Odoo Server Error
Occured on 172.20.18.5:8069 on model ir.cron and id 31 on 2025-03-18 12:02:43 GMT
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/tools/safe_eval.py", line 397, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
File "ir.actions.server(309,)", line 1, in
File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 5481, in _cron_account_move_send
self.env['account.move.send']._generate_and_send_invoices(
File "/home/odoo/src/odoo/addons/account/models/account_move_send.py", line 687, in _generate_and_send_invoices
self._generate_invoice_documents(moves_data, allow_fallback_pdf=allow_fallback_pdf)
File "/home/odoo/src/odoo/addons/account/models/account_move_send.py", line 612, in _generate_invoice_documents
self._prepare_invoice_pdf_report(batch)
File "/home/odoo/src/odoo/addons/account/models/account_move_send.py", line 333, in _prepare_invoice_pdf_report
content_by_id = self.env['ir.actions.report']._get_splitted_report(pdf_report.report_name, content, report_type)
File "/home/odoo/src/odoo/addons/account/models/ir_actions_report.py", line 60, in _get_splitted_report
pdf_dict = {res_id: stream['stream'].getvalue() for res_id, stream in content.items()}
File "/home/odoo/src/odoo/addons/account/models/ir_actions_report.py", line 60, in
pdf_dict = {res_id: stream['stream'].getvalue() for res_id, stream in content.items()}
AttributeError: 'NoneType' object has no attribute 'getvalue'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 1962, in _transactioning
return service_model.retrying(func, env=self.env)
File "/home/odoo/src/odoo/odoo/service/model.py", line 156, in retrying
result = func()
File "/home/odoo/src/odoo/odoo/http.py", line 1929, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
File "/home/odoo/src/odoo/odoo/http.py", line 2177, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
File "/home/odoo/src/odoo/odoo/http.py", line 727, in route_wrapper
result = endpoint(self, *args, **params_ok)
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 42, in call_button
action = call_kw(request.env[model], method, args, kwargs)
File "/home/odoo/src/odoo/odoo/api.py", line 533, in call_kw
result = getattr(recs, name)(*args, **kwargs)
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_cron.py", line 120, in method_direct_trigger
self.ir_actions_server_id.run()
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_actions.py", line 995, in run
res = runner(run_self, eval_context=eval_context)
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_actions.py", line 827, in _run_action_code_multi
safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True, filename=str(self)) # nocopy allows to return 'action'
File "/home/odoo/src/odoo/odoo/tools/safe_eval.py", line 411, in safe_eval
raise ValueError('%r while evaluating\n%r' % (e, expr))
ValueError: AttributeError("'NoneType' object has no attribute 'getvalue'") while evaluating
'model._cron_account_move_send(job_count=20)'
The above server error caused the following client error:
RPC_ERROR: Odoo Server Error
RPC_ERROR
at makeErrorFromResponse (http://172.20.18.5:8069/web/assets/0604b65/web.assets_web.min.js:3140:163)
at XMLHttpRequest. (http://172.20.18.5:8069/web/assets/0604b65/web.assets_web.min.js:3145:13)
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prGeolocation lookup no longer crashes when a contact or sub-contact has no name. This keeps the address lookup workflow stable and shows a clearer contact label when no match is found.
Original PR description
<b>Steps to reproduce:</b> 1. Install base_geolocalize and Contacts > Go to Contacts. 2. Create a new contact or select an existing one (Individual). 3. Go to Contacts & Addresses > Add, leave all…
<b>Steps to reproduce:</b>
1. Install base_geolocalize and Contacts > Go to Contacts.
2. Create a new contact or select an existing one (Individual).
3. Go to Contacts & Addresses > Add, leave all fields empty, then Save & Close.
4. Open the newly created sub-contact > Partner Assignment > Geolocation
5. Click "Compute based on address".
<b>Issue:</b>
- Traceback is raised during geolocation computation if the sub-contact has no name Instead of Displaying.
<b>Cause:</b>
- If a partner does not have a name, the value is False.
- The join() operation results in a TypeError because False cannot be concatenated with strings.
<b>Problematic line:</b>
`'message': _('No match found for %(partner_names)s address(es).', partner_names=', '.join(partners_not_geo_localized.mapped('name')))`
<b>Solution:</b>
- Replaced `name` with `display_name` to ensure all elements passed to`join()` are strings.
This also improves readability in the UI when identifying partners without proper names.
opw-4930258
Forward-Port-Of: odoo/odoo#218292This fixes an issue where manually adjusted tax amounts on Portuguese vendor bills could make the displayed untaxed total differ from the accounting entries. The tax summary now stays aligned with the posted bill values, reducing confusion during invoice review and accounting reconciliation.
Original PR description
Create a vendor bill with a base of 123 and 23% tax. => untaxed_amount = 123 & amount_tax = 28.29 Edit the tax amount to be 28.30 => The tax totals shows an untaxed_amount of 122.99 but the accounting entries say 123.0 This is because during the rounding, since the tax computation is custom in Portugal, we subtract the tax amount from the total amount to get the expected base amount. Since the total is not updated according the tax lines, the base amount takes the difference instead of the total. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Internal users can now convert Excel files in shared document folders into Odoo spreadsheets even when portal users have edit access on the folder. During conversion, portal users are limited to view-only access on the new spreadsheet, avoiding an error while respecting spreadsheet sharing rules.
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, even though the internal user has all the access rights. 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. --- This commit enables .xlsx to spreadsheet conversion only for internal users. The solution for portal users requires more complex implementation deserving its own review cycle, which is proposed in [PR #92134](https://github.com/odoo/enterprise/pull/92134) (PR #92134's first commit is the same commit as current PR's commit) opw-4753670
Payroll users in Belgium can now export work entries for any active company they have access to, instead of being limited to their current company. The export also now checks that the selected company has its required Group S code set, helping prevent incomplete or failed submissions.
Original PR description
before this commit only the current company was taken into account when exporting work entries now another company can be selected if multiple companies are active for the current user In addition to that this commit also add a check for the company's group s code to enforce the user to set it before exporting work entries task-4213675 closes old PR: odoo/enterprise/pull/71521
The Cash Flow report now handles grouping by account codes consistently, preventing an error that could block report generation. This helps accounting users access the expected report breakdown without disruption when account code fields are present.
Original PR description
The term used by GROUP BY should be the same term in the SELECT, avoiding the posible error like: ERROR: column "account_move_line__account_id.code_store" must appear in the GROUP BY clause or be used in an aggregate function That appears when a column named account_code is created for the model account_move_line. opw-4963180
This fixes an issue where nested grouped lines in account reports did not fold properly and could trigger an error when users expanded or collapsed partner lines. The change helps keep financial reports stable and easier to navigate when using grouped account data.
Original PR description
Steps to reproduce: - Create an Account Group - Create a new Account Report as follows: * Name: any * Lines: 1. [test line] * Group By: partner_id,account_id * Expressions: 1. [test expression] *…
Steps to reproduce:
- Create an Account Group
- Create a new Account Report as follows:
* Name: any
* Lines:
1. [test line]
* Group By: partner_id,account_id
* Expressions:
1. [test expression]
* Computation Engine: Odoo Domain
* Formula: [('account_id.account_type', '=', 'asset_receivable')]
* Subformula: sum
- Actions > Create Menu Item
- Open the new report
- Try to unfold/fold a partner line
Issue:
Folding will not fold the first child (representing the created account group). Also, error will raise
```
Uncaught Promise > Got duplicate key in t-foreach: ~account.report~37|~account.report.line~255|{'groupby': 'partner_id'}~res.partner~4226|~account.group~90
Occured on odoo.nas.cpolar.cn on 2025-04-26 04:58:53 GMT
OwlError: Got duplicate key in t-foreach: ~account.report~37|~account.report.line~255|{'groupby': 'partner_id'}~res.partner~4226|~account.group~90
Error: Got duplicate key in t-foreach: ~account.report~37|~account.report.line~255|{'groupby': 'partner_id'}~res.partner~4226|~account.group~90
at AccountReport.template (eval at compile (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:13743:20), <anonymous>:138:49) (/web/static/lib/owl/owl.js:5752)
at App.callTemplate (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:11363:50) (/web/static/lib/owl/owl.js:3372)
at AccountReport.template (eval at compile (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:13743:20), <anonymous>:9:12) (/web/static/lib/owl/owl.js:5752)
at RootFiber._render (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:9774:38) (/web/static/lib/owl/owl.js:1783)
at RootFiber.render (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:9766:18) (/web/static/lib/owl/owl.js:1775)
at ComponentNode.render (https://odoo.nas.cpolar.cn/web/assets/debug/web.assets_web.js:10493:23) (/web/static/lib/owl/owl.js:2502)
```
Analysis:
Folding issues occurs because of a mismatch in the grouping markup quote escape. If we don't have the very same string the controller cannot properly recognize the parent line and then is unable to fold/unfold properly.
This eventually led to the mentioned error at unfold as the backend will try to generate the apparently missing lines to unfold, only to create duplicate lines
opw-4754241The Journal Audit report PDF export now works when users filter by receivable or payable account types. This prevents an error screen during export and helps accounting teams generate audit documents reliably.
Original PR description
- In the Journal Audit report options, set the Account Type (filter_account_type) to either receivable, payable, or both. - Attempt to export the PDF of the Journal Audit report. A traceback occurs because, in _generate_document_data_for_export, we attempt to add a join using an alias. However, if the filter_account_type option is enabled, there is already a left join in the query with the same alias: account_move_line__account_id. opw-4926547
The Belgian payroll salary configurator now calculates the laptop benefit in kind correctly. This ensures employee salary packages reflect the right laptop value, aligning it with existing internet and mobile benefit handling.
Original PR description
The benefit in kind laptop salary rule was not adapted for the salary configurator. This commit fixes the issue by always returning the correct laptop value if the salary rule is used in a salary configurator, like it is already the case for the internet and mobile benefits. task-4971722
The outdated Sign Base Folder setting is now hidden because it no longer works. Users should manage folder choices through Sign Document Templates instead, reducing confusion in configuration.
Original PR description
The setting no longer works and will be removed in future versions. Users should configure folders via Sign Document Templates instead. task-4879652
Tickets created from Timesheets now automatically use the Helpdesk team linked to the selected project. This prevents tickets from being assigned to the wrong team and helps keep support work routed correctly from the start.
Original PR description
Steps to Reproduce: - 1. Go to Timesheets > My Timesheets, start the timer, and select the project linked to the helpdesk team. 2. In the timer header, quick-create a new ticket via the "Ticket" field dropdown 3. Observe that the default helpdesk team on the new ticket is incorrect. Issue: - - When creating a ticket from the Timesheets module (e.g., via timer header or views), the system selects an incorrect default helpdesk team, leading to misassigned tickets. Cause: - - The core default logic for team_id prioritizes user membership or the first team without considering the selected project's linked helpdesk team. Fix: - - Override `_default_team_id` to set the correct Helpdesk Team based on the selected project. - A domain has been added to the team selection field within the timesheet views to only show teams that have the timesheet feature enabled. task-4885679 Forward-Port-Of: odoo/enterprise#89503
The default 13th-month salary rate for Swiss payroll contracts has been adjusted from 8.33% to 8.3333%. This improves payroll calculation accuracy and helps ensure Swiss salary amounts are computed with the expected precision.
Original PR description
-changed the default contractual thirteen month rate for Switzerland from 8.33 to 8.3333 Forward-Port-Of: odoo/enterprise#92095
Work entries now calculate attendance-based durations correctly for employees on flexible schedules, even when the period starts midweek or covers only part of a day. This prevents holiday-related gaps from being incorrectly recorded as a full 8 hours, improving payroll and attendance accuracy.
Original PR description
### Steps to reproduce: - Set Marc Demo's contract work entry source to attendances and working schedule to flexible hours. - Create a public holiday with generic time off work entry type. - Create…
### Steps to reproduce: - Set Marc Demo's contract work entry source to attendances and working schedule to flexible hours. - Create a public holiday with generic time off work entry type. - Create one or multiple attendances for marc demo on the public holiday. - Regenerate work entries for marc demo for that day, the gaps in between the attendances created and the working hours will be filled with work entries with the right start/end time but duration will always be 8h. ### Cause: This is happening because when getting the duration batch for the work entry we get the attendance intervals the employee should work in that period and if the employee is flexible we will get a fake attendance with the number of hours required per day ignoring if the period is just a small period of the day ### Fix: We are checking now since the start date not monday so we don't set a fixed week start. We check if the period is less than the remaining hours we get it as it mostly means that it is less than one day opw-4887933
Upsell orders now prevent users from changing the commission plan when the original subscription has Freeze Plan enabled. This avoids confusion by matching what users can edit with the commission plan that will actually be used for payouts.
Original PR description
**Problem:** An inconsistent behavior occurs when a user changes the commission plan while creating an upsell order for a recurring Sales Order (SO). **Steps to reproduce:** 1) Install the…
**Problem:** An inconsistent behavior occurs when a user changes the commission plan while creating an upsell order for a recurring Sales Order (SO). **Steps to reproduce:** 1) Install the Subscriptions and partner_commission modules. 2) Create a subscription SO with a referrer_id and set a recurrence. 3) Enable the Freeze Plan option and create a commission plan from the view 4) Add a rate of 50 and product category as service in the commission rules. 5) In SOL add a subscription product contains recurrence with unit price of 100 6) Confirm the SO → Create Invoice → Confirm → Pay. 7) Go back to the SO and create an upsell for it. 8) Change the commission plan rate to 30 by creating a new plan. 9)Repeat step 4. **Issue:** When you navigate to the referrer record from the SO and open the Purchase Order via the smart button, you will see two Purchase Order lines both showing a value of 50, even though the upsell order had a new commission plan with a rate of 30. **Cause:** When the invoice is marked as paid, a Purchase Order with POL is created using values from the commission plan. For subscription orders, the system intentionally uses the subscription’s original commission plan instead of the updated one. https://github.com/odoo/enterprise/blob/03a5efc04538fce380ec3ea993e7586047fe117e/partner_commission/models/account_move.py#L197-L203 However, the problem is that the commission plan field remains editable in upsell SOs even when the parent SO has Freeze Plan enabled, misleading users into thinking the new commission plan will be applied. **Solution:** Make the commission plan field read-only for upsell SOs when the parent SO has Freeze Plan enabled. opw-4954307
The accounting reports test suite was adjusted to avoid using unsupported grouping settings with external report calculations. This prevents false test failures for complex tax reports, helping keep accounting report validation reliable.
Original PR description
The corresponding community PR (https://github.com/odoo/odoo/pull/221407) contains a fix that requires the _validate_engine constraint to reject any groupby value for the 'external' engine. Therefore, it is now needed that the test ensuring non-stored related fields can be used in groupby is adapted in order to also exclude those expressions when changing the groupby value of the lines using a custom engine on any of their expressions. Without that, complex reports like the annexes of the Luxembourgese tax report fail the test.
Swedish SIE4 imports now complete even when the file does not include previous-year information for opening balances. The importer uses a sensible fallback date and also retries with an alternate character encoding, reducing failed imports for affected accounting files.
Original PR description
**Issue**: Importing a SIE4 file without previous year information causes a traceback. **Steps to reproduce**: - Go to Accounting > Settings > Import - Import SIE 4 file - Check the box "Import account opening balances" - Select the right xml and observe the traceback **Cause**: The method `_prepare_sie4_opening_balance_move` tries to directly access the previous year: https://github.com/odoo-dev/enterprise/blob/6d4919658650a006c73d4aaf1f500d67723dda0d/l10n_se_sie4_import/wizard/import_wizard.py#L376C9-L376C58 This results in a traceback when the previous year is not present. **Solution**: Make `_prepare_sie4_opening_balance_move` more permissive by falling back to the day before the first day of the current year if the `-1` section is not there. **Additional Notes**: The client file does not support `UTF8` format, retry with the `ISO-8859-1` format in case of `UnicodeDecodeError`. opw-4894495 Forward-Port-Of: odoo/enterprise#89425
Fixes an error that could stop users from checking the status of a GSTR-1 return after the related exception email template was deleted. This helps Indian GST reporting workflows continue smoothly instead of showing a system traceback.
Original PR description
Steps to reproduce: - Delete the mail template `GSTR-1 Exception` - Accounting -> Reporting -> GST Return Period - Create a return period, Under GSTR1 click Push to GSTN - Click on the Check Status…
Steps to reproduce:
- Delete the mail template `GSTR-1 Exception`
- Accounting -> Reporting -> GST Return Period
- Create a return period, Under GSTR1 click Push to GSTN
- Click on the Check Status Button
The following RPC is produced:
```py
File "/home/odoo/src/enterprise/l10n_in_reports_gstr/models/gst_return_period.py", line 1261, in button_check_gstr1_status
self.check_gstr1_status()
File "/home/odoo/src/enterprise/l10n_in_reports_gstr/models/gst_return_period.py", line 1345, in check_gstr1_status
act_type_xmlid, advisor_user = self._get_gstr_responsible_activity_and_user()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/l10n_in_reports_gstr/models/gst_return_period.py", line 1271, in _get_gstr_responsible_activity_and_user
act_type = self.env['mail.activity.type'].sudo()._load_records({
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/models.py", line 5439, in _load_records
xml_ids = [data['xml_id'] for data in data_list if data.get('xml_id')]
^^^^^^^^
AttributeError: 'str' object has no attribute 'get'
```
In this commit, we resolve the above issue and restore the expected output
task-5010701Automatic currency rate updates from the Central Bank of the UAE now include the Sudanese Pound. This ensures businesses using SDG receive current exchange rates instead of having to update them manually.
Original PR description
**Steps to reproduce**: 1. Install the `account` and `l10n_ae` modules. 2. Go to `Invoicing → Configuration → Currencies` and activate the `Sudanese Pound (SDG)` currency. 3. Navigate to `Settings → Invoicing → Currencies → Automatic Currency Rates`. 4. Select `[AE] Central Bank of the UAE` as the currency provider and manually fetch rates. <img width="463" height="181" alt="image" src="https://github.com/user-attachments/assets/31257e2e-8360-4cdb-877e-2ea41487ddea" /> 5. Return to the Currencies list. **Observed behavior**: - The rate for the `Sudanese Pound (SDG)` is not updated. **Root cause**: - The `SDG` currency is missing from the `MAP_CURRENCIES` dictionary, so the provider doesn't fetch its rate. **Solution**: - Add the missing `SDG` currency mapping to `MAP_CURRENCIES`. opw-4869204 Forward-Port-Of: odoo/enterprise#91790
Appointment users can now create appointments from calendar events when the appointment uses a single resource. This removes an access error that previously blocked the booking flow, helping staff schedule appointments without administrator help.
Original PR description
Before this commit, trying to create an appointment through a calendar event as an user will raise an AccessError. This is because in this fix #76653 we needed to make sure the appointment_resource_id is being set on the calendar event and for this we needed to make it readonly. This causes that an user, is not able to get the proper access rights to read on to the 'appointment.booking.line' which is being triggered since inside each booking line, we have an appointment_resource_id which is a many2one to the appointment resource. To fix this, we are adding a sudo on the booking lines when we only have 1 booking line and the appointment resource is set on the calendar event. This way, the user will be able to read the booking lines and create the appointment. opw-4614976 Forward-Port-Of: odoo/enterprise#88373
Repeat website appointment bookings now reuse an existing contact when the same email is provided, instead of creating a duplicate record. This keeps customer data cleaner while respecting company boundaries in multi-company setups.
Original PR description
Booking an appointment on the website creates a new contact. If the same user books again, a duplicate contact is created instead of reusing the existing one. --- **Steps to Reproduce** 1. Book an…
Booking an appointment on the website creates a new contact. If the same user books again, a duplicate contact is created instead of reusing the existing one.
---
**Steps to Reproduce**
1. Book an appointment with a name, email, and phone.
2. Book a second appointment using the same data.
3. A new duplicate contact is created.
---
**Cause:**
In v18, the appointment booking flow lost the fallback email search mechanism that existed in v17. When `_get_customer_partner()` returns empty (anonymous users), the system immediately creates a new partner without checking if one already exists with the same email. This regression causes duplicate contacts to be created for repeat anonymous bookings.
**Root Issue:**
The v17 logic included an email search fallback:
```python
customer = request.env['res.partner'].sudo().search([('email_normalized', '=', email_normalized)], limit=1)
```
This was removed in v18, breaking the partner reuse mechanism.
**Solution:**
Restore the email search logic with multi-company awareness:
1. **Email Search**: When no customer is found, search for existing partners by normalized email
2. **Company Boundaries**: Limit search to partners without a company or belonging to the current company context to prevent cross-company data conflicts
3. **Fallback Creation**: Only create new partners when no compatible existing partner is found
---
This fix restores the fallback email search logic from v17, ensuring anonymous users booking appointments reuse their existing contact records while maintaining proper company data isolation in multi-company environments.
The search is limited to partners without a company or partners belonging to the current company to prevent cross-company data conflicts.
**opw-4614897**