Daily updates from Odoo
Thursday, August 21, 2025
22 changes · master
Enhancements to existing features
Users can now copy and paste carousel figures in Odoo spreadsheets, making it easier to reuse visual spreadsheet content without rebuilding it. This improves day-to-day spreadsheet editing and reduces manual work when preparing reports or dashboards.
Original PR description
This commit makes the spreadsheet clipboards work for carousel figures. Task: [5002886](https://www.odoo.com/odoo/2328/tasks/5017194)
Adds Latvia-specific EC Sales List and Intrastat support linked to VAT return submission. Users get clearer submission guidance, PDF access, filing deadlines, frequencies, and Latvian translations to help meet local reporting obligations.
Original PR description
Following the implementation of the Tax returns feature in 18.3 which was focused on the general implementation and Belgium, we want to add the specification for other country and in this case Latvia. EC Sales List is a part of this, with VAT Returns as the EC Sales List is generated when the VAT Return is submitted. Intrastat is a part of this which is generated when the VAT Return is submitted. We are showing modals with the instructions as well as a Download PDF button to make it easier for them to have access to the PDF since it's important for the users to have the instructions present when submitting those documents. This also includes the deadlines and frequencies for the generation of those documents, and also the translation of the instructions. task: 4893953
The referral buttons on job pages have been reorganized so the main Job Page action stays prominent, while sending and sharing options are grouped into clear dropdowns. This makes referral actions easier to find and gives the interface a more consistent, polished layout.
Original PR description
Changes - Kept "Job Page" as the first button. - Grouped "Send" actions under a dropdown - Grouped "Share" actions under a second dropdown - Standardized icons and alignment for consistency Task ID: 5017390
Payroll salary rules now pass tax information to accounting entries instead of relying on account tags. This improves payroll tax reporting, especially for Australian payroll, by allowing relevant amounts to be included correctly in tax closing entries.
Original PR description
Previously, account tags could be set on salary rules, and would be forwarded onto the corresponding journal items when the payslips are generated and translated into accounting. However, it was not the best way accounting-wise, especially if we want some amounts to be reflected in the tax closing entry (only a tax can do that, not tags). task-4479740
Bank reconciliation can now create separate automatic matching rules for the same account when statement descriptions differ. This helps accountants get more accurate suggestions from repeated transactions such as rent payments across different months.
Original PR description
In the community pr, we removed the uniqueness constraint on the name of a reco model. Indeed, when doing a set account on multiple statement line, we check if there is a common substring and create…
In the community pr, we removed the uniqueness constraint on the name of a reco model. Indeed, when doing a set account on multiple statement line, we check if there is a common substring and create a reco model if there is one. But the reco model created has the name of the account. Which means that we couldn't have two automatically generated reco model for the same account. This commit will remove the check to see if a reco model already exist for that account. Since we now want to have the possibility to have different reco model for the same account. Changed the name of the reco model created to avoid having 2 reco models using the same account that have the same name. Also change the way we compute the longest substring because it was not working for all cases. For example: Let's make 3 statements lines: Rent March, Rent May, Rent April. The current method will get the longest substring between the two first which is Rent Ma and then compare with the third one. But the longest common substring should have been Rent. task-4876374
Users working with marketing automation mailings can now open the complete mailing form instead of a small dialog. This makes it easier to design and edit mailings with access to the full set of options in a more comfortable workspace.
Original PR description
Purpose ========= To provide users with easy access to the complete form view of mailing, ensuring a comfortable design experience. Specification ============= This commit modifies linked action and 'create and edit' for the mailing field to open full form view instead of dialog. Task-3901336
Replenishment from the Master Production Schedule now carries the selected bill of materials into the manufacturing order. This helps ensure production uses the intended components and process when a product has multiple manufacturing options.
Original PR description
Before this commit, on replenishment triggered a MO without considering the BoM on that product. Now `bom_id` is passed as one of the values in the procurement to make sure the correct BoM is used in the manufacturing order. Task: 4920000
Message composer drafts now store content as HTML so plain text and rich text composers can use the same draft field. This improves consistency across messaging workflows and supports richer draft handling without changing the user-facing process.
Original PR description
This commit updates the text field in composer model to use HTML instead of plain text. This change is made to ensure that the html composer can share the same field as the text composer. Also, this commit renames the text field to draftContent in a variety of places. https://github.com/odoo/odoo/pull/223397
Users can now copy and paste carousel figures within Odoo spreadsheets using the standard clipboard workflow. This makes it easier to reuse spreadsheet visuals and reduces manual rebuilding when preparing reports or dashboards.
Original PR description
This commit makes the spreadsheet clipboards work for carousel figures. Task: 5002886
Appointment setup now makes one-off flexible availability easier to create and manage directly from the appointment form. Businesses can apply normal booking restrictions, such as minimum notice and assigned users or resources, to these flexible slots while benefiting from cleaner filters and a simpler booking calendar.
Original PR description
PURPOSE ======= Some users would like to use unique slots instead of having recurring ones. This can only be done from the share availabilities button in the calendar view. While the appointment can…
PURPOSE ======= Some users would like to use unique slots instead of having recurring ones. This can only be done from the share availabilities button in the calendar view. While the appointment can be modified, it is not intuitive to do it that way. We want to make the 'custom' appointments easier to use and accessible. MAIN CHANGES ============ As 'custom' appointment type means 'flexible' schedule and vice versa, we do not store any more field. Instead, we use an editable computed selection field that allows the user to switch between options with the radio widget, and update category and slots accordingly in the onchange and inverse (on category) methods. As custom appointments are likely to get more frequent, and to be used in various contexts, we now allow restrict_to_x_ids for unique slots and effective min_schedule_hours. NEW SLOT CONSTRAINT =================== Since unique slots are easier to user, let us add a sql constraint to ensure that the start_datetime and end_datetime are set for the unique slots, and that start_datetime <= end_datetime. We make sure we correctly update the slots when changing the category in the appointment type form (see onchange and inverse methods) OTHER CHANGES ============= - In a separate commit, remove chevron counters and related code as deemed low-value and disposable. - New 'Flexible' filter and 'recurring' renamed to 'weekly' - Some tests are added to ensure constraint and form reactivity on category change. For options as well. UPGRADE ======= - We remove the 'invitations' submenu in the configuration that allowed to see all 'custom' appointments. It is not relevant anymore and is replaced with an available filter on the appointment.type search view. We also remove the associated view. - We remove ill-configured slots. As they are only used to generate slots and not linked to other records, we can remove them altogether. (constraints would still make them fail in the booking flow, so they are not really working anyway) UPG PR: https://github.com/odoo/upgrade/pull/8206 Task-4997980
Return status handling is now managed centrally in Python, so adding country-specific statuses no longer requires manual view changes. This reduces maintenance effort and lowers the risk of inconsistent or missed status updates across reporting modules.
Original PR description
Before this commit, adding specific states to a return was tedious as it was required to add a field in Python and add overrides in the view using t-set, ... Now everything is done on the Python side we do not have to change the view anymore when adding new states. This is dynamically computed based on the result of '_get_state_field' and the current_state. Also we noted an important thing, we should never set the state from the base field directly but by using the 'state' field. This will automatically trigger the write on the corresponding field and ensure everything is synchronized. This is because we do not want to have to add every new state field in the depends of the compute as it is error prone; we might forget it. Using a common way of writing the state is easier. task-5012501
PDF signing fields now refresh when the document viewer redraws a page instead of on a fixed timer. This reduces visible flickering and provides a smoother signing experience for users.
Original PR description
PDF.js, the library used for the rendering of the PDFs, sometimes tears down the whole page and rerenders it from scratch. Because of this, we have to add our custom sign fields on top periodically to avoid them disappearing. Currently, we render all the fields every second but this leaves a window between them disappearning and being rerendered which shows as the fields flickering. With this PR we want to transition the rerendering of the fields from a periodic nature to an event-based nature by catching the event of the page being rerendered from the eventBus of PDF.js Task: 4999789
Sign templates can now include a default validity period in days, so new signature requests automatically receive an expiration date. This reduces repetitive setup work and helps teams apply consistent signing deadlines across documents.
Original PR description
Added a field to sign templates for setting a default validity period (in days) for sign requests. This streamlines the process by eliminating the need to manually set an expiration date for each new request. task-4942996
The calling features previously labeled as VoIP are now presented as Phone across the app. This makes the feature easier for users to recognize and understand, while preserving the existing calling functionality.
Original PR description
Task-4987530
Resolved issues and error corrections
Fixed a point of sale preparation display issue that could cause an error when a restaurant used only one preparation stage. Staff can now mark that single stage as Reset or Done without the preparation screen crashing, improving reliability for simpler kitchen workflows.
Original PR description
This error occurs when we try to mark a single stage as `Reset` or `Done` in the preparation display. Steps to reproduce: --- - Install the `pos_restaurant` module - Create a New `Preparation Display` with one stage - Open `Preparation Screen` - Now `Reset` or `Done` the stage in the other tab Traceback: --- `IndexError: tuple index out of range` At [1], an error occurs because it tries to access a `position` that doesn't exist in the tuple. This happens because at [2], the code attempts to retrieve the second-to-last (-2) stage position, but only one stage is being used. [1]- https://github.com/odoo/enterprise/blob/285cca92a52f7b79de1d020558aa9b116cd7e44a/pos_enterprise/models/pos_prep_stage.py#L21-L22 [2]- https://github.com/odoo/enterprise/blob/285cca92a52f7b79de1d020558aa9b116cd7e44a/pos_enterprise/models/pos_prep_state.py#L72 sentry-6681171781 Forward-Port-Of: odoo/enterprise#87098
The Kitchen Display no longer crashes when an order is marked done on a preparation display that has only one stage. This keeps restaurant order workflows running smoothly for setups with simplified preparation stages.
Original PR description
Currently, an IndexError traceback occurs when changing the order state in the preparation display if it contains only one stage. **Steps to reproduce this issue:** 1) Install POS, Kitchen Display 2)…
Currently, an IndexError traceback occurs when changing the order state in the preparation display if it contains only one stage. **Steps to reproduce this issue:** 1) Install POS, Kitchen Display 2) Create a preparation display by removing all but one stage in the prep settings. 3) Open a restaurant session and create an order. 4) Open the preparation display and mark the created order as DONE. 5) A traceback will occur **Error:** ``` IndexError: tuple index out of range ``` **Cause:** When the Done button is clicked in a preparation display with only one stage, an ORM call to `change_state_status` is triggered. This then calls `_record_status_change_prep_time`, followed by `is_stage_position`. https://github.com/odoo/enterprise/blob/39810b5b7df01f381a08582ddc0c5218e99c964c/pos_enterprise/models/pos_prep_state.py#L31-L40 https://github.com/odoo/enterprise/blob/39810b5b7df01f381a08582ddc0c5218e99c964c/pos_enterprise/models/pos_prep_stage.py#L21-L22 In `is_stage_position`, static positions [0, -1, -2] are used to access items in the `stage_ids`. If only one stage exists, accessing indices -2 results in an IndexError. **Solution:** Before accessing a stage by position, check that the length of stage_ids is greater than or equal to the absolute value of the position. This prevents attempts to access out-of-range indices. opw-4985306 Forward-Port-Of: odoo/enterprise#91918
Contact map locations now stay in sync when a company's address changes, preventing outdated markers for related child contacts. This helps users trust the Map View when maintaining customer or company address data, though a known import edge case may still require re-importing or updating the parent contact.
Original PR description
**Issue:** When adding contacts with incorrect address data, the Map View could display outdated or incorrect markers **Cause:** The `partner_latitude` and `partner_longitude` fields were not reset…
**Issue:** When adding contacts with incorrect address data, the Map View could display outdated or incorrect markers **Cause:** The `partner_latitude` and `partner_longitude` fields were not reset for child contacts when the parent’s address changed **Fix:** We added a `partner_latitude` and `partner_longitude` reset when changing address in write We added `partner_latitude` and `partner_longitude` in the _address_fields to update the value each time it can be required, like on address change or contact creation The extension in the _address_fields is there to detect the changes on children synchronization, because it only replace the value that where present in vals for the fields in that list In that way, it will detect more address changes and trigger the write for the children with the corresponding parent `partner_latitude` and `partner_longitude` We also make sure that those extra _address_fields will not be displayed in the formatted address by removing them from `_formatting_address_fields` **Limitations:** One issue remains during import: the parent-child address synchronization is disabled on contact creation This means children may be created with addresses different from the parent’s and have mismatch positions on Map This can be corrected by updating or re-importing the parent to trigger synchronization **Steps to reproduce:** With Form: - Add a parent contact company with a valid address - Add a child contact related to company, with a valid address - Open the Map View, both address must appear on Map - Modify the parent address to remove street (make it invalid) - Check that the child address match the parent one - Check the Map View, before the fix the child should remain with a wrong position With import: Create an import file (an example is in on the ticket) - Add a sheet for the Parent contact with an valid address - Add a sheet to add the Child contact with a parent_Id, with a valid address - Add a sheet to break the address on the parent, removing the street - Open the contacts app - Import the valid Parent and Child sheets (you need to select Related Company / External ID) - Add a filter to get your created contacts - Check the Map View (You should see both parent and child) - Import the Break parent sheet - Check that the child address match the parent one in the Form - Check the Map View, before the fix the child should remain with a wrong position A file can be found on the ticket with pre-made data **Technical notes:** The reset logic is duplicated from the `base_geolocalize` module, because this module is optional and may not be installed in all cases Since `base_geolocalize` is not always present, its `write` override will not be triggered consistently On the other hand, `web_map` is automatically installed with the Enterprise version of Odoo Therefore, it is necessary to implement this fix in at least one of the two modules to ensure the behavior is active when Enterprise is used We chose to keep the override in both `base_geolocalize` and `web_map` to cover both Community and Enterprise cases reliably An alternative approach would be to move the reset logic directly into `res.partner` in the `base` module, making it always available regardless of installed addons and avoiding the duplication opw-4842910 Forward-Port-Of: odoo/enterprise#92658 Forward-Port-Of: odoo/enterprise#90392
Swedish SIE4 accounting imports now continue even when the file does not include previous-year information, avoiding an import crash. The importer also retries with an alternate text encoding when needed, helping customers process more client-provided files successfully.
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…
**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#92174 Forward-Port-Of: odoo/enterprise#89425
Files added through the email wizard when sending a Sign request are now included in the outgoing email. This prevents recipients from missing documents that users intentionally attached, restoring expected email behavior.
Original PR description
Issue: * When users added attachments in the mail wizard (e.g., from the Sign module), the files were saved in the backend but not included in the outgoing email. Steps to Reproduce: 1. Edit a Sign template and click the Send button. 2. In the wizard, click on the Attachments button and select a file. 3. Press Send. 4. The email is sent, but the selected attachment is missing from the Sign request mail. Fix: * Adjusted the logic to correctly include attachments added through the wizard in the final email. Impact: * Users can now successfully send attachments added via the mail wizard. * Restores expected behavior and prevents missing documents in email. task-5002652 Forward-Port-Of: odoo/enterprise#91975
Users without shipping method administration rights can now request DHL shipping rates without hitting an access error. This keeps the quotation flow working smoothly when adding DHL delivery costs.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Have DHL (legacy) as a delivery method; 2. log in as demo user; 3. create a quotation with a shippable product; 4. click "Add shipping"; 5. select DHL; 6. click "Get rate". Issue ----- > Access Error: > You do not have enough rights to access the field "dhl_account_number" on Shipping Methods (delivery.carrier). Cause ----- The error gets thrown in the `_set_dct_bkg_details` method. In previous versions, the `dhl_account_number` field would still be in cache after `srm.check_required_value` was called, as this method checks whether the `carrier.dhl_account_number` field is non-empty in sudo mode. As of saas-18.3, field access is checked even if the value is available in cache, resulting in the access error. Solution -------- Use `sudo` to retrieve the `dhl_account_number`. opw-4899776 Forward-Port-Of: odoo/enterprise#92557
The accounting payment widget now shows remaining bank statement balances correctly after partial reconciliation and applies the right currency conversion. It also prevents unrelated matched invoices from being undone when one partial payment is unreconciled, improving reliability for accounting teams.
Original PR description
[FIX] account_accountant: fix multi_currency payment_widget To reproduce: - Make a statement line for partner_a for 200 $ - Make an invoice for same partner for 100 $ - Reconcile it with the…
[FIX] account_accountant: fix multi_currency payment_widget To reproduce: - Make a statement line for partner_a for 200 $ - Make an invoice for same partner for 100 $ - Reconcile it with the statement line - Duplicate the invoice and post it => First issue, you don't see the 100$ left on the statement line It's still reconciliable To fix that, we only remove fully reconciled statement lines. Second issue: - Have a bank journal in EUR with a rate of 2 - Make a statement line for 400€ in this journal - Create an invoice for the same partner of 100$ => The widget proposes a statement line of 400$ instead of a 200$ equivalent (with the rate conversion) The issue is that we convert with a foreign_currency_id that is not present in that case. To fix both, we change the way we compute the amount to always use the residual converted from the right currency [FIX] account_accountant: partial on statement line for invoice widget To reproduce: - Make a statement line for partner_a for 200 $ - Make 2 invoice for same partner for 100 $ - Reconcile them with the statement line (via the widget) - Unreconcile first invoice via the payment widget => The second invoice is also unreconciled To solve: Only unreconcile the lines that are part of the partial that we want to unlink Forward-Port-Of: odoo/enterprise#92334 Forward-Port-Of: odoo/enterprise#92005
This fix stops automatically added helper fields from being displayed or treated as editable elements in Odoo Studio. It prevents incorrect layout calculations and editing issues, making Studio views behave more reliably for users.
Original PR description
…lly added since commit odoo/odoo@6f06420e4a9443c52dc0cb427f8f55eb4aecabce, fields that are present in expression but not in the arch are automatically added. This caused problems in Studio, where those were considered normal nodes, while they should only be there to tell the model what to fetch. This commit aims at not rendering those nodes in a way that prevent them from parasiting the computation of xpaths. opw-4981741 Forward-Port-Of: odoo/enterprise#92789 Forward-Port-Of: odoo/enterprise#92602