Friday, August 29, 2025
61 changes · master
New functionality added to Odoo
A new VAT Books report is now available for Spanish accounting, helping businesses review and export VAT-related records more easily. The Spain reporting menu also now includes direct access to VAT Books and Libro Diario, with an added XLSX export option for the journal audit.
Original PR description
In this PR: - Added 'VAT Books' report. - Added 'Libro Diario XLSX' button in Journal Audit view (XLSX export). - Introduced a dedicated submenu for Spain with: - 'Vat Books' report - 'Libro Diario' linking to the Journal Audit. task-4831718
Enhancements to existing features
The Mail message composer now supports inserting emojis directly from the emoji picker when using the HTML composer. This makes writing messages more convenient and improves the user experience around focus and text entry.
Original PR description
This commits allows html composer inserting emoji from emoji picker. Auto focus and related hooks changes accordingly. task-5022232 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This fixes a crash that could happen while creating a new website and choosing a shop layout in the setup flow. The configurator no longer points to an outdated setting, so users can complete website shop setup without interruption.
Original PR description
Steps to reproduce: 1) Create a new website and proceed to website configurator 2) When reaching 'Shop' selection page choose the second one and proceed 3) See a traceback Commit 670b1daa2254d7600b54bae675dd673f457aa8fa updated website settings and missed adapting the website configurator.
Spreadsheet list headers now remain consistent across user languages, preventing pivots based on lists from breaking when colleagues open the same spreadsheet in another language. Dashboard list tables also gain easier sorting from header cells, making it simpler to compare best and worst performers in common business dashboards.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
POS receipts now display loyalty points earned and the customer's current points balance. This gives shoppers clearer reward information at checkout and helps staff communicate loyalty benefits more transparently.
Original PR description
Before this commit: =================== - The receipt screen did not display any details about loyalty points won or the current loyalty point balance. After this commit: ================== - Loyalty point details (points earned and balance) are now displayed on the receipt screen. Task: 5022234 | saas-18.3 and above | This PR | |--------|--------| | <img width="391" height="844" alt="image" src="https://github.com/user-attachments/assets/c0ca55c0-cd46-468c-bb16-b19da5daa742" /> | <img width="391" height="844" alt="image" src="https://github.com/user-attachments/assets/1dd6d398-693b-4ab7-a598-520d6f8d8c56" /> | Forward-Port-Of: odoo/odoo#224466 Forward-Port-Of: odoo/odoo#223396
Odoo can now reload its main server without interrupting normal HTTP traffic in supported deployments. This reduces downtime during operational restarts and includes small reliability fixes around worker handling.
Original PR description
Component of Odoo task: https://www.odoo.com/odoo/project/1105/tasks/2946044 Currently, the server reload option (through the `server_phoenix` mechanism) activated by sending a SIGHUP signal to the…
Component of Odoo task: https://www.odoo.com/odoo/project/1105/tasks/2946044 Currently, the server reload option (through the `server_phoenix` mechanism) activated by sending a SIGHUP signal to the main process. This came with a consequential downtime while the server was restarting. This commit changes it to reload the server with no downtime (POSIX + Prefork mode) When a SIGHUP signal is sent to the main server, it will now initiate the shutdown procedure in a separate process that will first wait until the main process has finished restarting and is ready to handle new incoming HTTP requests. The reexecuted server will reuse the same socket and notify its stopping fork with a SIGHUP signal, which will then proceed with the graceful shutdown procedure. It will not be able to reap the children processes, so it will monitor them closely in a slightly different way using psutil. The newly restarted server will reap them without consequence. Note: the gevent longpolling server is not handled gracefully. (+ a couple of small fixes)
Users can now define monetary values in property fields, making it easier to capture amounts with the correct currency context. When available, the system will automatically use the model's default currency field, reducing setup effort and helping ensure consistent financial data.
Original PR description
This commit introduce the monetary type in to properties fields. The property needs a currency field (many2one field with a "res.currency" relation) to work. The currency field can be chosen and the field "currency_id" would be chosen by default if it exists on the model. task-5016664
Creating a project from a template now fills in project dates when none are provided. This saves manual setup time by using today's date as the start and calculating the end date from the template's planned duration when available.
Original PR description
This PR allows automatically setting dates when creating a project from a template. If no dates are set on creation, the start date defaults to today, and the end date is calculated according to the duration of the template, if it has planned dates. Task-4700745
This update improves how users add or remove many-to-many tags directly from list views. It makes bulk tag changes clearer and more controlled by adding confirmation handling, reducing the chance of accidental updates.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website managers can now control how shop and category pages present titles, descriptions, and centered content. This makes online store pages easier to customize without developer help and improves mobile navigation with a simpler category breadcrumb.
Original PR description
This PR introduces options for the categories and /shop page. Feature: - Create category specific options - Opt. Show/Hide title on categories and /shop - Opt. Center Content (title, desc, filmstrip) on categories & /shop - Opt. Show/Hide description on categories Note: since we now have an option to center the filmstrip, `w-100` is not viable to solve the rendering on safari. This bug was due to a miscalculation of the `flex-basis`, we now use a width instead. [task-4711722](https://www.odoo.com/web#id=4711722&cids=1&menu_id=4720&action=333&active_id=1695&model=project.task&view_type=form) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Event organizers can now set how many tickets a customer may order per ticket type, replacing the previous fixed limit of 9. The checkout experience is also improved with plus and minus quantity controls, while safeguards keep limits reasonable for performance and security.
Original PR description
**Currently** When purchasing tickets online, a selectbox limits the value between 0 and 9 per ticket type. **Implementation** We have added a new field since the event was created, allowing this old hardcoded maximum limit to be modified. For performance and security reasons, this limit cannot exceed 99. The value 0 also indicates this maximum limit. The selectbox has been replaced with a spinner (inputbox with -/+ buttons). It improves the user experience by replicating certain behaviors of the native inputbox of `input type=number` but using the -/+ buttons instead of the old native arrows. **Tests** Some Website Event tours have been modified as a result of the change from the selectbox to the inputbox. The tours have also been completed to verify the new limits according to the configured constraints. task-4822074
Resource attendance setup has been simplified by replacing date range fields with clearer full-day and duration options. This makes working time calendars easier to review and adjust, reducing manual effort and confusion for teams managing schedules and leave planning.
Original PR description
- Added 'full_day' as a selection value for `day_period` - Displayed `duration_hours` in the list view - Made `duration_hours` editable and compute `hours` based on it - Removed `date_from` and `date_to` fields for simplification Task: 4929940 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
HR screens now separate the official contract type from the pay category, so each value is shown clearly in its own place. This helps payroll and HR teams avoid confusion while preserving the official contract names employees and administrators expect to see.
Original PR description
This change ensures that official contract names remain visible while clearly distinguishing them from the salary structure category. task-5013761
This change lets Odoo keep a minimum number of decimal digits for float values, making amounts, quantities, prices, taxes, and electronic document exports display more consistently. It helps reduce rounding confusion across accounting, purchasing, inventory, manufacturing, point of sale, and product workflows.
Original PR description
task-4895014
Calendar views can now be filtered using fields that link to multiple records, such as assignees. This prevents errors when opening affected calendars and gives users consistent filter options in the sidebar.
Original PR description
This commit adds support to filter a calendar view with x2many fields. Previous behavior: - When adding a x2many filter to a calendar view, a JS TypeError is thrown. Current behavior: - The calendar view now loads successfully with a x2many filter. - The dynamic filters sidebar correctly displays options for the x2many field (e.g., "Assignees" from `user_ids`). - Filters behave consistently with `many2one`-like selection and formatting. Imp: #215495 task-4897018
New websites can now include e-commerce content blocks, such as product carousels, directly during the initial website setup. This helps online stores launch with more relevant homepage content without requiring manual editing after creation.
Original PR description
Previous Behaviour: - Snippets existing in the website module could only be added to pages of a website when generated via website configurator. - Manifest of all themes have their own…
Previous Behaviour:
- Snippets existing in the website module could only be added to pages of a website when generated via website configurator.
- Manifest of all themes have their own `configurator_snippets` that defines what snippets will be rendered on the pages.
Expected Behaviour after the PR is merged:
- Snippets existing in other modules such as `website_sale`, etc. can now add their snippets to the pages via website configurator.
- Previously these snippets could only be used via drag & drop method from the editor after the website is already generated.
For adding non-website snippets into the pages of website:
- For website snippets, names can be given directly like `s_text_image`, etc. but for non-website snippets, the module prefix is required. (e.g., `website_sale.s_dynamic_snippet_products`).
- Module specific snippets can be defined in their own module's manifest(for default theme) and in the theme's manifest as addons to `configurator_snippets` like:
```
'configurator_snippets_addons': {
'website_sale': {
'homepage': [
('website_sale.s_dynamic_snippet_products', 'after', 's_cover'),
],
},
},
```
- `s_cover` is the reference snippet existing in the above `configurator_snippets` and `'after'` is the position, hence the `s_dynamic_snippet_products` will be rendered on the homepage after the `s_cover` snippet.
- If `'after'` is replaced with `''` then the snippet will be appended before the reference snippet.
For default configuration:
- Dynamic snippets need some default values such as filter-id, template-key, etc. to load completely.
- All required default values for a snippet to render should be defined in the const file existing in the module where snippet exists under `SNIPPET_DEFAULTS` - like:
```
SNIPPET_DEFAULTS = {
'website_sale.s_dynamic_snippet_products': {
'filter_xmlid': 'website_sale.dynamic_filter_newest_products',
'template_key':
('website_sale.dynamic_filter_template_product_product_products_item'),
'data_attributes': {
'snippet': 's_dynamic_snippet_products',
'carousel-interval': '5000',
'product-category-id': 'all',
'number-of-elements': '4',
'number-of-elements-small-devices': '2',
'show-variants': 'true',
},
},
}
```
For theme-level snippet customization:
- Snippets in themes may require customizations to match with theme standards, for that we can define them in theme's manifest like:
```
'theme_customizations': {
'website_sale.s_dynamic_snippet_products': {
'data_attributes': {
'number-of-records': '7',
'carousel-interval': '3000',
},
'background': {
'color': 'o_cc3',
'shape': {
'data-oe-shape-data': '{"shape":"web_editor/Wavy/07","flip":["x"]}',
'element': """<div class="o_we_shape o_web_editor_Airy_07_001">""",
},
},
},
}
```
task-4502087
Co-authored-by: Bojabza Soukéina (sobo) <sobo@odoo.com>This update improves Odoo spreadsheets and dashboards by adding easier sorting on list and pivot-style dashboard data, such as Top 10 reports. It also fixes language-related issues so dashboards built by users in different languages remain reliable, and includes visual/data file cleanup plus spreadsheet stability fixes.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/8ee7677ba [REL] 18.5.0-alpha.12 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/8ee7677ba [REL] 18.5.0-alpha.12 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/38658ed81 [IMP] dashboard: sort pivot from headers [Task: 4543812](https://www.odoo.com/odoo/2328/tasks/4543812) https://github.com/odoo/o-spreadsheet/commit/ccd7efa1d [REF] pivot: move sorting detection to getters [](https://www.odoo.com/odoo/2328/tasks/) https://github.com/odoo/o-spreadsheet/commit/90bd67c89 [IMP] collaborative: more robust readonly [Task: 4543812](https://www.odoo.com/odoo/2328/tasks/4543812) https://github.com/odoo/o-spreadsheet/commit/5b706da6f [FIX] composer: fix import from lib [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/318e3b619 [IMP] demo: add new data generator [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/fe37c4661 [FIX] borders: Recompute borders on `SET_BORDERS_ON_TARGET` [Task: 5024825](https://www.odoo.com/odoo/2328/tasks/5024825) Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya <rmbh@odoo.com> Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Projects created from templates can now automatically plan task dates based on the timing used in the original template. This helps teams start new projects with realistic schedules while still allowing the system to adjust dates to avoid conflicts.
Original PR description
This PR allows planning dates when a project is created from a template. The dates of the created tasks are calculated based on the dates of the task in the template project. Tasks will be scheduled based on the elapsed time between the start of the project and the start of the task in the template. Tasks are scheduled using the smart scheduling algorithm, so the time ranges might not be exact to avoid conflicts, etc. If the template doesn't have planned dates, tasks will be simply scheduled from the start of the created project (or today) using the smart scheduling. Task-4700745
This update makes account return and audit screens clearer and more reliable for users. It fixes navigation and display issues, adds better completion notifications, uses more appropriate dates during setup, and helps prevent duplicate return creation.
Users can now download TDS and TCS tax reports directly as Excel files instead of manually selecting export fields. The file includes the relevant return-filing information and is grouped by section to make review and filing easier.
Original PR description
Receives many feedback from the users that they currently exports report by manually selecting fields to file TDS & TCS return. The problem is many users are unaware of how to export it with existing fields. With this commit, users can now directly download the Excel file from the TDS/TCS Tax report, which includes all the relevant fields needed for filing TDS/TCS returns. Additionally, the XLSX file is grouped by section to make it easier to read. task-4945885 COM PR: https://github.com/odoo/odoo/pull/220707
VoIP call transcription now handles failed uploads more reliably, so users see the correct status instead of calls getting stuck as pending. Calls can also show a short transcript summary and clearer status banner, with demo examples and broader tests added to improve confidence.
Original PR description
Following up on the quick merge of the voip transcription aa5983efc390dc16cff3ee99a55a8878d6e06939 We are improving its state by modifying: **Controller**: doesn't raise errors anymore, returns http…
Following up on the quick merge of the voip transcription aa5983efc390dc16cff3ee99a55a8878d6e06939 We are improving its state by modifying: **Controller**: doesn't raise errors anymore, returns http err codes, keeping transcription_status persist errors (ref.1) **Tests**: added backend controller tests and cron tests covering happy paths and edge cases. (ref.2) **Summary**: added one_liner_summary filed on the voip call, which is generated after successful transcription; (if it fails we still have transcription) **Banner**: Previously we informed user about the transcription_status with a selection field in a view. Now it is replaced by a status banner at the top of the form view **Demo**: added some demo calls to showcase calls in all transcription_status. (ref.3) (ref.1) Without it: when we have an error in the request to transcribe it will rollback the transaction. Example: Controller is asked to transcribe, it can't because the file is too big, so it sets transcription_status=too_big_to_process **and raises**. This revers the transaction resulting in transcription_status set to pending. BAD (ref.2) To avoid gymnastic of creating second cursor for the sake of testing cron try to commit, we restrict committing so it doesn't happen in the test_mode. Subsystem testing covers those <img width="1139" height="408" alt="image" src="https://github.com/user-attachments/assets/90736892-58ce-4a15-b28d-bb8bf4369888" />
Payroll salary rules are now treated as updateable configuration, making it easier to keep standard payroll logic aligned during upgrades. Businesses that need custom payroll behavior should create or duplicate their own rules so those customizations remain protected during migrations.
Original PR description
Purpose ======= Rules that are supposed to be customized and kept over migrations should be created by hand, or duplicated from existing structures.
Employee records now show the official contract type separately from the payroll salary structure category. This helps HR teams keep legally or officially named contracts visible while still seeing the payroll classification needed for compensation processing.
Original PR description
This change ensures that official contract names remain visible while clearly distinguishing them from the salary structure category. task-5013761
Employee work schedule handling has been simplified by removing start and end date limits from resource attendance records. This reduces configuration complexity and supports cleaner payroll and scheduling processes, including Belgian payroll version handling.
Original PR description
Removed date_from and date_to fields for simplification Task: 4929940
This update improves how decimal numbers are displayed and handled by ensuring float fields can keep a minimum number of digits. It helps maintain consistent precision in accounting, payroll, delivery, point of sale, quality, and electronic invoicing workflows, reducing formatting inconsistencies across documents and integrations.
Original PR description
task-4895014
Partner ledger and related customer follow-up reports now include reconciliation date information, giving finance teams clearer context on payments and outstanding balances. This helps users review customer accounts more accurately and align follow-up actions with the latest reconciliation status.
The partner ledger now supports an additional closing date filter, making it easier to view open items up to a specific date. This helps finance teams produce more precise partner balance and reconciliation reports.
Payroll configurations for Jordan and Saudi Arabia now include the missing account mappings for salary rules. This helps ensure payroll entries are posted to the correct accounting accounts, reducing manual corrections and improving reporting accuracy.
Original PR description
xx: jo, sa In this commit we add the maping for all the salary rules accounts Taks: 4882398
Spreadsheet list headers are now kept consistent across user languages, so pivots based on lists continue to work when a spreadsheet is opened by colleagues using a different language. Several spreadsheet dashboard files were also reformatted to make future updates cleaner without changing their business content.
Internal VoIP calls made using extension numbers are now matched to the corresponding Odoo user. This helps employees recognize who is calling instead of seeing only an extension number.
Original PR description
**Purpose:** Improve the user experience by identifying internal calls made using extension numbers (voip usernames) by displaying the corresponding user's name. **Specification:** Enhance the get_contact_info method in the voip.call model to resolve internal extensions by matching the call's phone_number with the voip_username field on res.users. **Task**-4997542
This fixes an issue where the Point of Sale could fail to start if the default preset required a customer. Stores using customer-required presets can now initialize the POS reliably, reducing disruption at checkout.
Original PR description
Before this commit, if the POS default preset required a partner, an error would occur during initialization. opw-5023987 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224144 Forward-Port-Of: odoo/odoo#223355
Spreadsheet list headers now use a consistent, untranslated label so dashboards and pivots keep working when opened by users in different languages. This prevents reports built by one user from breaking or showing mismatched fields for colleagues using another language.
Original PR description
Current issue: Alice's language is in English and Bob is in French. Alice inserts a list in a spreadsheet, and create a pivot with the dataset being the list. Alice chooses the pivot dimensions based…
Current issue: Alice's language is in English and Bob is in French. Alice inserts a list in a spreadsheet, and create a pivot with the dataset being the list. Alice chooses the pivot dimensions based on the columns headers, which are the translated(!) field display names. Now Bob opens the spreadsheet. => the pivot doesn't work because the dimension are specified using the field names in English, but they cannot be found because they are in French in the spreadsheet. The issue is that `ODOO.LIST.HEADER` returns the translated field string. One solution would be drop `ODOO.LIST.HEADER` completely and just hard-code the string values when the list is inserted. But users use it to add fields after, and then auto-fill it. Also, being easily able to know which cells are list headers is helpful to display "widget" like the sorting widget (task 4543812) Other thing to consider: currently, when users are creating their own spreadsheet/dashboard, there's a mix of languages: what they manually type in cells, in their language (untranslated obviously) and the result of ODOO.LIST.HEADER, which is translated. Task: 4805206 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
Customer invoice lists can now be sorted by the Status and Sent columns. This makes it easier for accounting users to organize invoices and quickly find records based on payment or sending progress.
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 Forward-Port-Of: odoo/odoo#222357
This fixes Dutch electronic invoices so the correct identifier type is used when a company has a 20-character Peppol OIN number. It helps ensure NLCIUS invoice XML files meet the expected Peppol requirements and reduces rejection or compliance issues when exchanging invoices electronically.
Original PR description
## Short functional explanation of the error For Dutch companies, when downloading the NLCIUS file of an invoice, the schemeID of the companyID in the XML isn't correct. ## Reproduction Steps 1. Make…
## Short functional explanation of the error For Dutch companies, when downloading the NLCIUS file of an invoice, the schemeID of the companyID in the XML isn't correct. ## Reproduction Steps 1. Make sure you use a dutch company: in apps, download the 'l10n_nl' and 'account_edi_ubl_cii' modules. Then, click on your company and select the NL Company. 2. Go to settings and type Peppol. Under Customer Invoices, check the Peppo format. Then, setup a Peppol Endpoint. Hit save. 3. Go to the Accounting app and click on the customers tab, then invoices. Click on new. 4. Select a customer. Make sure that the customer is from the Netherlands, has an email address, and in the accounting tab, an account number. Still in the accounting tab, under Electronic Invoicing, set the format at NLCIUS, set a Peppol e-address and a Peppol Endpoint that is 20 characters long. 5. Add a product, click confirm then Send & Print. Make sure that NLCIUS is well checked and click again Send & Print. 6. In the bottom right corner of the page, just under the Amount Due, there's a paper clip icon. Click on it and you'll see the XML. Download it. ### Expected behavior As the CompanyID is 20 characters long, the schemeID next to the CompanyID should have the value of 0190. ### Unexpected behavior If you scroll a bit, you'll see that the SchemeID next to the CompanyID has a number of 0106. ## Origin of the issue In the code, the SchemeID will have a value of 0190 if the CompanyID is 9 characters long. __ opw-4943262 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223431 Forward-Port-Of: odoo/odoo#219424
Early payment discounts are now applied based on the discount deadline saved on the posted invoice, not on later changes to the payment term setup. This ensures customers receive the discount they were originally promised and prevents missed discounts during payment registration or reconciliation.
Original PR description
When a payment term with early payment discount is used on invoice the discount date is set on the payment term line based on the actual configuration of the payment term. When the invoice is posted,…
When a payment term with early payment discount is used on invoice the discount date is set on the payment term line based on the actual configuration of the payment term. When the invoice is posted, this date must not change anymore as it usually is what is communicated to the partner in order to apply EPD. However, if the payment term's delay for discount is modified, the discount date from the move line was not taken into account by the payment register wizard or by the reconciliation widget, as it was instead recalculating a discount limit date, based on the configuration of the payment term at the time the payment is registered on Odoo. Make sure it is the discount date that is stored on payment terms' account move line that is used to define if an early payment discount has to be applied. OPW-4895365 Description of the issue/feature this PR addresses: On runbot, create a new payment term with an early payment discount (eg 10% at 15 days, balance at 30 days). Create a customer invoice with a invoice line (eg 100 USD) for any customer with this payment term and set the date to 10 days before today. Post the invoice, you can see on the payment term line that the discount is valid until 5 days after today. Modify the payment term to set 10% at 5 days. If you go back to the invoice, you'll notice the discount date is still 5 days after today which is fine since this is what was communicated to the customer Current behavior before PR: Register a payment on this invoice and you'll notice the EPD is not applied because it gets the date from the actual configuration of the payment term instead of the date stored on the invoice's payment term line. Desired behavior after PR is merged: Register a payment on this invoice must apply the EPD as it is still valid based on the invoice's payment term line. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224044 Forward-Port-Of: odoo/odoo#215615
This fixes an issue where choosing a record from a search dialog could unexpectedly open the record form instead of selecting it. Users can now complete selections as intended, reducing confusion when using custom fields and related records.
Original PR description
Example of steps: - install web, purchase and studio - add a many2one with studio anywhere and choose purchase.order.line - close studio - try to use this new field, select "Search more" - select a random record - It opens the form view record instead of select It This is because purchase order line has an openAction that forces the opening of a form view. However, for a select_create_dialog, we must bypass this action to allow nothing except selection. To do this, a new prop has been added, “allowOpenAction,” in the list_controller, which will be true by default, but will be false for select_create_dialog. opw-4958121 Forward-Port-Of: odoo/odoo#223416 Forward-Port-Of: odoo/odoo#222602
Point of Sale now handles cases where a loyalty program used on an order is archived in the backend. This prevents reload errors and helps cashiers continue working smoothly even when loyalty programs are changed administratively.
Original PR description
Before this commit, archiving a loyalty program while it was actively applied to an order could lead to errors. Specifically, if a PoS order had an active loyalty program applied, and that program was subsequently archived from the backend, reloading the PoS interface would cause issues or prevent proper functionality due to the program's sudden unavailability. opw-4941044 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218814
Updates Odoo's EU distance selling VAT mapping to reflect Romania's fiscal change effective August 1, 2025, replacing the former 5% and 9% reduced VAT rates with the new 11% reduced rate. This helps businesses apply the correct VAT when selling between Romania and other EU countries.
Original PR description
As of August 1, 2025, Romania implemented significant changes to its fiscal code: - The 5% and 9% reduced VAT rates were unified into a single reduced rate of 11% This commit updates the EU distance selling VAT mapping to reflect these changes: - From Romania to each EU country - From each EU country to Romania task-5005391 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222644
This fixes an issue where payroll leave work entries that had already been validated could still be modified while resolving overlapping leave entries. The change helps keep approved payroll and leave records stable during module installation or future-dated scenarios.
Original PR description
This logic of solving the overlapping between leave work entries has been adjusted to prevent editing the entries marked as validated. This error appears in the installation in task #4921300. You can refer to the error here: https://runbot.odoo.com/runbot/build/87127472 To reproduce: -Fake time a date in the future, for example :"2025-09-05 UTC". -Install the needed modules with demo data: -i "hr_payroll,project_timesheet_holidays" --with-demo. Forward-Port-Of: odoo/odoo#224636
The calendar view now opens a confirmation form before splitting a work entry, using the existing entry details and setting the split duration to half by default. This makes the split action behave correctly and gives HR users a clearer, safer flow when adjusting work entries.
Original PR description
This commit fixes how the split button behaves in the Calendar view of the work entry. Instead of calling the ORM function upon clicking the split button, the split button now opens a `FormViewDialog`. The save button in the dialog is modified so that, instead of saving the record data, it calls the `action_split` function that handles the splitting logic. The context is used to open the dialog with a custom form view that has read-only fields, and the form is populated with the existing work entry data, except for the duration, which is set as half of the existing work entry duration. A new form view is created and used in the dialog. task-5043857 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixed an issue in Point of Sale where confirming an order could also send an unrelated draft order when a customer was selected. This prevents accidental draft order synchronization and helps keep sales records accurate.
Original PR description
Before this commit, in a non-restaurant PoS, when selecting a partner in a draft order, validating an order would also sync the draft order. opw-5037759 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224041
Point of Sale now shows a clear Access Denied pop-up instead of an error when certain admin users without product category permissions open sample POS sessions. This prevents a confusing crash and helps users understand they need additional access rights from an administrator.
Original PR description
Currently, an error occurs when a new user with the Member role and Administrator rights for the Point of Sale app attempts to open POS Category. Steps to reproduce: --- - Install the `point_of_sale`…
Currently, an error occurs when a new user with the Member role and Administrator rights for the Point of Sale app attempts to open POS Category.
Steps to reproduce:
---
- Install the `point_of_sale` module (without demo data).
- Create a new User and give Administrator rights for POS & Accounting
- Now log in with a new user in a different browser
- Open the pos session(Clothes or bar)
Traceback:
---
```py
AccessError: You are not allowed to modify 'Product Category' (product.category) records.
This operation is allowed for the following groups:
- Products/Admin en Products / Create
Contact your administrator to request access if necessary.
ParseError:while parsing /home/odoo/src/odoo/saas-18.3/addons/point_of_sale/data/scenarios/clothes_category_data.xml:5, somewhere inside <record id="product_category_clothes" model="product.category">
<field name="name">Clothes</field>
</record>
```
This commit prevents the error by displaying an "Access Denied" pop-up when a user with the "Member" role and Administrator rights attempts to open the POS Category.
sentry-6683335275, 6679363278, 6823710988
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#224656
Forward-Port-Of: odoo/odoo#215429Fixes an issue where unbuilding a completed manufacturing order could be blocked if a component was later changed to require lot or serial tracking. Businesses can now reverse past production reliably while keeping the normal tracking requirements for components that were tracked at the time of manufacture.
Original PR description
**Description of the issue/feature this PR addresses:** This PR fixes a regression when using the _Unbuild_ feature on a previously completed `mrp.production` whose components did not originally…
**Description of the issue/feature this PR addresses:** This PR fixes a regression when using the _Unbuild_ feature on a previously completed `mrp.production` whose components did not originally require tracking (no lot/serial), but have been updated later to require it. When unbuilding such a product, `stock.move.line._action_done` currently raises a UserError requiring a lot/serial number, because the component moves created by `mrp.unbuild`: - do not have a picking_type_id, - are not inventory moves, - are not scrap moves, - and lack lot/serial information. However, in this context, the lot requirement is misleading, as the original `mrp.production` did not generate tracked components. It is valid to restore untracked components even if they are now tracked. **Current behavior before PR:** - Create an `mrp.production` for a product with untracked components. - Complete the production. - Later, enable lot tracking on one or more of the original components. - Attempt to unbuild the production. - ❌ Error is raised: “You need to supply a Lot/Serial Number for product…” **Desired behavior after PR is merged:** - The unbuild operation proceeds without error. - The untracked components are restored correctly. - Behavior remains unchanged for tracked components that did require lot info during the original MO. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222612 Forward-Port-Of: odoo/odoo#217282
The Manufacturing app installation was optimized for companies with very large stock movement histories. This reduces the risk of installation failures, timeouts, or excessive memory use when enabling Manufacturing on large databases.
Original PR description
Description ----------- On large databases with millions of already existing `stock.move`, the post-install computation of compute stored fields can be time-consuming and memory intensive. This commit extends the pre_init_hook that was done in `mrp` to: - Speed up computation of `stock.move.is_done` - Implement SQL query to initialize `stock.move.manual_consumption`. Reference --------- opw-4980036 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222299
When an individual customer is linked to a company, their assigned pricelist now stays aligned with the company instead of unexpectedly changing on quotations. This helps sales teams keep customer pricing consistent and avoids accidental use of the wrong price list.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Create an individual partner; 2. assign them a pricelist A; 3. create a new company partner for them; 4. create a new pricelist A & sort it on top; 5. open a…
Versions
--------
- 18.0+
Steps
-----
1. Create an individual partner;
2. assign them a pricelist A;
3. create a new company partner for them;
4. create a new pricelist A & sort it on top;
5. open a new quotation;
6. set new company as customer;
7. change customer to the individual partner.
Issue
-----
The quotation's pricelist changed from B to A. The pricelist used for the individual should be identical to the one used for their company.
Cause
-----
Commit de302c2d36305 added the `specific_property_product_pricelist` field to `res.partner`, as the way company-dependent fields are managed was changed on the database-level.
Commit 67cf577cd0a0 added the `_company_dependent_commercial_fields` method to enable syncing company-dependent commercial fields. The base method fetches all fields retrieved via `_commercial_fields`, and selects those whose `company_dependent` attribute is `True`.
In previous versions, the `_company_dependent_commercial_fields` override in `product` adds `property_product_pricelist`, as this field does not have the `company_dependent` attribute set, but it behaves as a company-dependent field. Starting from 18.0, the override adds `specific_property_product_pricelist` instead, which does have the `company_dependent` property set.
As a consequence, when `_company_dependent_commercial_sync` gets called, it does not sync the `specific_property_product_pricelist` as it's not included in the `_commercial_fields` override, nor does it sync when retrieving it from `_company_dependent_commercial_fields`, as it skips the current company, assuming the field was already handled by `_commercial_sync_from_company`: https://github.com/odoo/odoo/blob/c40760244d128cb57e11a233e89a93dd92b8fb56/odoo/addons/base/models/res_partner.py#L667-L668
Solution
--------
- Move `specific_property_product_pricelist` to `_commercial_fields`
- This enables it to sync in `_commercial_sync_from_company`
- Remove the `_company_dependent_commercial_fields` override
- `property_product_pricelist` shouldn't get synced by itself
- `specific_property_product_pricelist` is already included by the base method
opw-4988736
Forward-Port-Of: odoo/odoo#224133
Forward-Port-Of: odoo/odoo#222223Fixed an issue where starting two IoT WebRTC connections almost at the same time could cause the connection to fail. The update prevents duplicate connection attempts while one is already opening and adds test coverage to reduce the risk of this happening again.
Original PR description
If two calls are made to open a WebRTC connection within a short space of time, they will both try to open a new connection causing a failure. This commit fixes the issue by checking to see if a connection is currently opening before continuing. It also adds a unit test for this scenario.
UK tax report submissions to HMRC now include the correct obligation ID. This prevents submissions from failing or being sent with missing reference information, improving reliability for UK tax filing workflows.
Original PR description
Issue: Prior to this commit, when sending a tax report to HMRC, the obligation ID was undefined Fix: sending the appropriate obligation ID opw-4965620 Forward-Port-Of: odoo/enterprise#91735
The Spanish SME balance sheet now avoids counting certain current financial investment accounts twice. This ensures reported investment amounts match the underlying accounting entries, improving confidence in financial statements.
Original PR description
**Issue**: * Amounts were exactly doubled in 'Current financial investments' (line 12500) in the Spanish Balance Sheet - SMEs report as account codes 551 and 5525 were incorrectly included in…
**Issue**: * Amounts were exactly doubled in 'Current financial investments' (line 12500) in the Spanish Balance Sheet - SMEs report as account codes 551 and 5525 were incorrectly included in balance_pymes_line_12500_sub_balances formula **Root Cause**: * Account codes 551 and 5525 were included in BOTH: 1. Line 12500 sub_balances (unfiltered account_codes expression) 2. Line 12500 sub_debits (domain expression with sum_if_pos filter) * This double-counting within the same line caused financial investment amounts to appear twice in the balance sheet **How to Reproduce**: 1. Create Spanish company with 'es_pymes' chart of accounts 2. Post journal entries to accounts 551 or 5525 (current financial investments) 3. Generate 'Balance Sheet - SMEs (ES)' report 4. Observe amounts in line 'V. Current financial investments' are exactly doubled compared to account balances 5. Click on the doubled amount - shows underlying transactions sum to half the amount **Fix**: * Removed account codes 551 and 5525 from balance_pymes_line_12500_sub_balances * These accounts are properly handled by the sub_debits expression * Each account is now counted only once within the line opw-4983300 Forward-Port-Of: odoo/enterprise#93052
Quality checks on manufacturing orders can now proceed without users first entering the producing quantity. This removes an obsolete validation that is no longer needed because invalid manufacturing quality point setups are already prevented elsewhere.
Original PR description
This commit reverts the change from: [PR](https://github.com/odoo/enterprise/commit/51a9b38), which had introduced a `UserError` that occurs when creating a quality point with operation type `Manufacturing` having control per `quantity`. Revert is done since this [PR](https://github.com/odoo/enterprise/pull/67780) now prevents creating quality points with operation type `Manufacturing + control per quantity`, which makes the original bugfix PR unnecessary and has become dead code. After this commit, quality checks on manufacturing orders no longer require setting the producing quantity first. Task ID: [4915067](https://www.odoo.com/odoo/project/966/tasks/4915067)
Spreadsheet list headers are now stored consistently so pivots keep working when users open the same spreadsheet in different languages. This prevents dashboards and custom spreadsheets from breaking for multilingual teams and also standardizes dashboard file formatting for easier maintenance.
Spreadsheet list headers now stay consistent regardless of each user's language settings. This prevents pivots and dashboards based on list columns from breaking when opened by colleagues using a different language.
Original PR description
Current issue: Alice's language is in English and Bob is in French. Alice inserts a list in a spreadsheet, and create a pivot with the dataset being the list. Alice chooses the pivot dimensions based…
Current issue: Alice's language is in English and Bob is in French. Alice inserts a list in a spreadsheet, and create a pivot with the dataset being the list. Alice chooses the pivot dimensions based on the columns headers, which are the translated(!) field display names. Now Bob opens the spreadsheet. => the pivot doesn't work because the dimension are specified using the field names in English, but they cannot be found because they are in French in the spreadsheet. The issue is that `ODOO.LIST.HEADER` returns the translated field string. One solution would be drop `ODOO.LIST.HEADER` completely and just hard-code the string values when the list is inserted. But users use it to add fields after, and then auto-fill it. Also, being easily able to know which cells are list headers is helpful to display "widget" like the sorting widget (task 4543812) Other thing to consider: currently, when users are creating their own spreadsheet/dashboard, there's a mix of languages: what they manually type in cells, in their language (untranslated obviously) and the result of ODOO.LIST.HEADER, which is translated. Task: 4805206
Point of Sale badge printing now loads the needed badge format information again. This restores badge printer functionality for event check-ins and reduces manual work for staff using PoS at events.
Original PR description
Due to an oversight in odoo/enterprise#83021, printing badges using the badge printer from POS was not working. This commit fixes the issue by restoring the `badge_format` field to the list of fields loaded in the POS. Forward-Port-Of: odoo/enterprise#93365
GSTR document summaries now ignore invoices that no longer have a valid sequence number. This prevents report generation errors and ensures only properly numbered invoices are included.
Original PR description
_* = l10n_in_reports_gstr_document_summary Issue: - The GSTR document summary included all invoices that were posted or cancelled with posted_before = True. - If a user manually cleared the invoice sequence (set it to null), such invoices were still picked up. - This caused errors during summary generation since those invoices no longer had valid sequence numbers. Fix: - Adjusted the document summary logic to only include invoices with a valid sequence number. - Ensures that entries without a sequence are ignored, even if they were once posted. Impact: - Prevents errors when generating GSTR document summaries. - Guarantees that only valid, numbered invoices are included in reports. opw-5005048 Forward-Port-Of: odoo/enterprise#93039
This fixes an issue in Barcode receipts where removing scanned serial-number lines could remove the wrong item. Users can now decrement and re-enter serial numbers without false duplicate warnings, reducing receiving errors for tracked products.
Original PR description
Steps to reproduce: - Install Purchase, Stock and Barcode apps - Create a product tracked by serial number - Create a PO of this product and confirm it (demand 3) - Open Barcode application for the PO's receipt - Start entering serial numbers for the 3 products - For each line, use the decrement button and remove all 3 lines - Make sure the last removed line is not the first scanned serial - Re-enter the serial number of the last removed line Issue: The parent line of the 3 sublines has the lot_name fixed on the first scanned serial_number. So when decrementing the last_line, it will always use the virtual_id of the first serial_number scanned, leading to decrementing the wrong serial number. It starts showing that the next scanned number is already used, because it wasn't properly removed in the first place. opw-4646765 Forward-Port-Of: odoo/enterprise#89987 Forward-Port-Of: odoo/enterprise#88130
Portal users receiving published planning shift emails are now sent to the correct planning page instead of the portal dashboard. This helps external or limited-access users view their schedules directly from email without confusion or extra navigation.
Original PR description
### Steps to reproduce: - Install Planning app - Create a portal user and an employee for this user - Create a shift for this user and Publish it - Go to the email that has been sent and click on…
### Steps to reproduce: - Install Planning app - Create a portal user and an employee for this user - Create a shift for this user and Publish it - Go to the email that has been sent and click on View Your planning - Notice you are redirected to the portal dashboard home ### Cause: Since this commit diff we removed the check if the user is having planning group https://github.com/odoo-dev/enterprise/commit/72afe1e14703f0a3eafd0cfaec10c67462db73ce#diff-293bc9f44292d19793981abbafbe2a55642d170bda5e3bf17d7654f7bffcbedaL62-L64 When getting the planning url that will be share in the email we don't check if the user is portal or not so we set the url with /odoo path and if a portal user is accessing a /odoo path it will redirect him to /my https://github.com/odoo/odoo/blob/1acf4b2ce2bdad27e7d32d1227698968148a5935/addons/portal/controllers/web.py#L25-L26 ### Fix: We check if the user is portal we set the url with /planning path which will redirect the portal user to the correct planning view opw-5045746 Forward-Port-Of: odoo/enterprise#93359 Forward-Port-Of: odoo/enterprise#93333
Recurring subscription orders with timesheet-based services are no longer incorrectly treated as free when work has already been delivered. This ensures invoices are generated for delivered service work even when the original order quantity or recurring amount is zero, helping prevent missed revenue.
Original PR description
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product…
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product and set the qty to 0 - Create a Helpdesk ticket and link it to the SO - Record some timesheets in this SO - Run the cron for generating recurring invoices - Notice no invoice will be created for the SO and it will be considered as free renewal ### Cause: When trying to create a recurring invoice we check if the invoice that will get generated is free by checking the MRR and the total amount of the SO and if one of them are 0 we will flag this invoice as free so we won't generate it ### Fix: We check if the order lines to be invoiced is invoiced based on delivery and they have delivered quantity already and if so we create the invoice even if the MRR and the total amount is equal 0 opw-4990478 Forward-Port-Of: odoo/enterprise#93245 Forward-Port-Of: odoo/enterprise#93115
Managers can now access VoIP call records for employees across their full reporting line, not just direct reports. This fixes incomplete visibility for teams with multiple management levels and helps managers review relevant call activity more reliably.
Original PR description
This commit fixes the record rules that specifies the users that can read phone calls made through VoIP. Currently, managers can only access call records of their direct subordinates. They should have access also to calls made by employees that are managed by their direct subordinates. This commit fixes that. Task-5033984
The fix ensures that signing request email buttons direct recipients to the website of the company that sent the request, rather than defaulting to another company’s website. This reduces confusion for signers and helps avoid business or legal issues caused by documents appearing under the wrong company.
Original PR description
According to a ticket, when you have 2 companies and send a sign request from the second one, the button in the email received from the signer redirects to the website of the first company. This may cause confusion and may have legal implications. This PR aims to fix the problem by correctly targeting the right website. Task & ticket: 4976533
The work entry split action in the Gantt view now opens a confirmation form instead of trying to split immediately. This helps HR users review the split details first and prevents incorrect or failed split actions.
Original PR description
This commit fixes how the split button behaves in the Gantt view of the work entry. Instead of calling the ORM function upon clicking the split button, the split button now opens a `FormViewDialog`. The save button in the dialog is modified so that, instead of saving the record data, it calls the `action_split` function that handles the splitting logic. The context is used to open the dialog with a custom form view that has read-only fields, and the form is populated with the existing work entry data, except for the duration, which is set as half of the existing work entry duration. task-5043857
GSTR2B reconciliation now skips vendor bills that do not include any taxes. This prevents bills that vendors likely did not file from appearing in the reconciliation process, making Indian GST reporting more accurate.
Original PR description
Before this commit- We included the Vendor bills without taxes for GSTR2B reconciliation After this commit- We exclude the Vendor bills without taxes for GSTR2B Because if no tax is there on the bill it means wasn't filed by the Vendor as well task-5023013 Forward-Port-Of: odoo/enterprise#93373 Forward-Port-Of: odoo/enterprise#92866
The subscription invoicing process now skips subscriptions linked to archived companies. This prevents hidden or inactive company records from continuing to generate recurring invoices unexpectedly.
Original PR description
Currently, when a company which has recurring orders (subscriptions) active is archived, the cron still periodically invoices them as usual but the user is not able to see it because they don't show up in the views. To avoid having to unarchive the comany and check every subscription one by one, this PR aims at making the cron ignore any subscription tied to an archived company, as intended. The only modified cron is the one that creates invoices since the other one of interest (the one that sends reminders) operates only on invoiced orders, which we avoid having with this change. Also added a test to ensure that if the company related to a subscription sale order is archived, the cron won't invoice it. Task: 4947107