Tuesday, October 7, 2025
22 changes · saas-18.4
Enhancements to existing features
The Brazilian AvaTax product form now shows “LC116 Code” instead of “Mercosul NCM Code” when configuring services. This reduces confusion by using the correct terminology for service tax codes while keeping product code labeling unchanged.
Original PR description
Purpose:- - In Brazil, NCM is a code that has an acronym to specify the Mercosul Common Name for products, and for services, the right name is LC116 (Complementary Law 116), which specifies the federal code for a service. - But we have the same field `l10n_br_ncm_code_id` to configure both NCM for goods and LC116 for services and the same table can be used for both the cases. - So while configuring fiscal information for a service, user don't understand why it still shows the NCM label instead of LC116. Before this commit:- - Label `Mercosul NCM Code` was displayed for services confusing users. After this commit:- - Label `Mercosul NCM Code` is replaced with `LC116 Code` only for services. - Tooltip is also improved for better understanding. task-5096435 Forward-Port-Of: odoo/enterprise#96228 Forward-Port-Of: odoo/enterprise#95404
This update streamlines how developers configure website builder options, making related settings easier to keep together and reuse. It mainly affects appointment, online booking, and rental website features, helping future improvements be delivered more consistently with limited direct user impact.
Original PR description
The commit: 1. use static property to configure a builder option 2. introduce the concept of dependencies to access the plugin's shared in builder option 3. make a plugin context the same for Plugin,…
The commit:
1. use static property to configure a builder option
2. introduce the concept of dependencies to access the plugin's shared
in builder option
3. make a plugin context the same for Plugin, BuilderOption and
BuilderAction to have the same API in each class.
Before this commit, to define an option, we had to define a javascript
object that would contain the information of the option within the
`builder_options` resource.
```js
class MyPlugin extends Plugin {
resources: {
builder_options: [
{
selector: "div.selector",
template: "my.owlTemplate",
cleanForSave() {}
// ... other option props
}
]
}
}
// For a custom component
class MyPlugin extends Plugin {
resources: {
builder_options: [
{
selector: "div.selector",
template: MyCustomComponent,
cleanForSave() {}
// ... other option props
}
]
}
}
class MyCustomComponent extends BaseOptionComponent {
// ...
}
```
When building anything for the builder, there is 3 classes that are
important: `Plugin`, `BaseOptionComponent`, `BuilderAction`.
In practice, the option object defined in builder_options feels
strange. On the other hand, making the configuration of the option as
a static property of the component somehow feels simpler as everything
related to that option is defined in the same class.
```js
class MyPlugin extends Plugin {
resources: {
builder_options: [MyCustomComponent]
}
}
class MyCustomComponent extends BaseOptionComponent {
static template = "my.owlTemplate";
static selector = "div.selector";
static cleanForSave(context) {}
// ...
}
```
To have the same mental context in the 3 important class, they all
share the same API (`dependencies`, `dispatchTo`, `getResource`, ...)
(see `Editor.getPluginContext`)
To access a plugin shared method, it's now the same for `Plugin`,
`BuliderAction` and `BaseOptionComponent`:
```js
class MyCustomComponent extends BaseOptionComponent {
static selector = "mySelector";
static dependency = "myPlugin";
myMethod() {
this.dependencies.myPlugin.pluginMethod();
}
}
```
To access a resource, dispatch, ...:
```js
class MyCustomComponent extends BaseOptionComponent {
static selector = "mySelector";
myMethod() {
const resource = this.getResource('myResource');
}
}
```The website HTML builder now has a cleaner internal way to define and manage editing options. This should make future builder improvements easier to develop and maintain, with little direct change for end users.
Original PR description
1. use static property to configure a builder option 2. introduce the concept of dependencies to access the plugin's shared in builder option 3. make a plugin context the same for Plugin, BuilderOption and BuilderAction to have the same API in each class. See https://github.com/odoo/odoo/pull/220746
This update adds automated checks for appointment booking flows, including capacity handling, availability, cart bookings, invoice confirmation, and final event creation. These tests help reduce the risk of booking errors and improve reliability across appointment sales and payment scenarios.
Original PR description
\* = website_appoinment_sale, appointment_account_payment Add tests to ensure correct behaviour for the various scenarios. The following tests are added: - Users/resource's capacity computation when manage capacity is on and off. - Unavailability computation of users/resources in the `calendar.event`. - Check the bookings of user/resource in the cart for the availability after the invoice is confirmed. - Creation of the actual event when the booking from the cart is confirmed. Task-4919317
Resolved issues and error corrections
The message shown when fetching bank transactions finds no results now displays correctly instead of showing raw formatting tags. This makes the banking workflow clearer and more professional for users when filters or transaction fetches return no matches.
Original PR description
Before this commit : - The help message shown when no transactions were fetched by the 'Fetch Transactions' button in the 'Bank' journal contained raw html tags, as markup was not getting applied. - Also, removing a filter (without reloading) and applying another filter that resulted in no matches, the same issue occurred. After this commit: - The help message is now consistently rendered with markup applied. task-4942234 Forward-Port-Of: odoo/enterprise#95514
Documentation and clarification updates
This updates the recorded corporate contributor agreement information for ForgeFlow. It keeps Odoo's legal contribution records current and does not change product functionality for users.
Original PR description
Forward-Port-Of: odoo/odoo#230040
Miscellaneous changes
Fixes a typo in the i18n directory. no task-id Forward-Port-Of: odoo/enterprise#96417
Original PR description
Fixes a typo in the i18n directory. no task-id Forward-Port-Of: odoo/enterprise#96417
The website profile email validation banner now remains hidden after a user closes it. This prevents confusing repeat messages about email validation and creates a smoother account experience.
Original PR description
### Issue 1: The validated email success banner wasn’t triggering the RPC call because Bootstrap’s `data-bs-dismiss="alert"` removed the element from the DOM before the handler could run. ### Issue 2 Closing the banner previously triggered `/profile/validate_email/close` RPC, which reset `validation_email_done` to false. This mistakenly caused the “email sent” banner to reappear, confusing users. ### Solution - Overwrite Bootstrap’s `close.bs.alert` event to trigger the RPC when the success banner is dismissed. - Set `validation_email_sent = False` so the banner stays hidden after being closed. Task-5049533 Forward-Port-Of: odoo/odoo#229913 Forward-Port-Of: odoo/odoo#225872
Fixes Belgian EC Sales List reporting when a company's VAT number was entered without the country prefix. This prevents incorrect trimming of VAT numbers and ensures Belgian reports consistently use Belgium as the country code.
Original PR description
It could happen that the user set his vat number without the country code before the number. In this case, we removed the two first digits of the vat number. Also changing other occurrence using the company_vat to get the country, since we are in the belgian ec sale list, the country_code should be 'BE' everytime task-5039969 Forward-Port-Of: odoo/enterprise#93377
This fix makes Mail channel mention suggestions more reliable when replying in channel threads. It corrects a test setup and mock response format so the issue is consistently covered and future regressions are easier to catch.
Original PR description
Back-port of https://github.com/odoo/odoo/pull/230157 https://runbot.odoo.com/odoo/runbot.build.error/233201 Problematic line introduced: https://github.com/odoo/odoo/pull/209240 Test introduced: https://github.com/odoo/odoo/pull/226563 Test adapted to be more deterministic: remove current user from channel to ensure the channel is always found through the suggestion route. Fixed returned format of mock server.
Employees with flexible working hours will no longer see weekends automatically marked as unavailable in the timesheet grid. This prevents misleading greyed-out days for people who can choose when they work, making time entry clearer and more accurate.
Original PR description
To reproduce: ============= 1- Update employee worktime to be flexible 2- Go to timesheets -> saturday & sunday are marked grey Problem: ======== Can't apply https://github.com/odoo/odoo/blob/ce2d134d3e8e5c0d96529c1d0490f1e0c5e28294/addons/resource/models/resource_calendar.py#L511 This logic cannot be applied when an employee's work time is flexible, since they can work whenever they want. Fix: ==== When employee work time is flexible we just return empty list for the unavailable dates. opw-5031144 Forward-Port-Of: odoo/enterprise#96181 Forward-Port-Of: odoo/enterprise#94346
Odoo now handles Gelato cancellation updates without crashing when a removed email template is no longer available. Instead of trying to send that missing notification, it records the cancellation status in the sales order chatter so teams can still see the update.
Original PR description
After an order is canceled on Gelato, we receveive a webhook with an `fulfillmentStatus` of `cancel` and while processing it, it crash with: ``` ValueError: External ID not found in the system: sale.mail_template_sale_cancellation ``` The mail template used to notify the status change has been removed in odoo/odoo@2c858ed15e50, so instead we simplify log the information on the sale order chatter. opw-5110226 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230121
Opening the Helpdesk ticket list with no tickets now works correctly instead of crashing. This improves reliability for teams starting with an empty ticket queue or after clearing all tickets.
Original PR description
When accessing the Helpdesk ticket list view with zero tickets, the view previously crashed due to improper handling of folded sample data. This commit ensures that sample data folding does not trigger errors when the view is empty, improving overall stability. Steps to reproduce: 1. Navigate to Helpdesk > Teams > Tickets. 2. Ensure there are no tickets. 3. Switch to list view. Task-4971510
Users can now create automated actions in Documents that generate journal entries for credit card journals. This fixes a blockage that prevented credit card statement workflows from being set up correctly.
Original PR description
We are unable to create an action to create a credit card statement on a journal with type credit card Allow to create a Server Action to create Journal Entries in journals of type "Credit Card" in Documents. task-5123868 Forward-Port-Of: odoo/enterprise#95905
This fixes an issue where users could paste text into protected, non-editable areas while editing website content. The change helps preserve locked content and prevents accidental modifications in the website builder.
Original PR description
When the selection is on text inside an element which is not `contenteditable` and is a inside the editable root, the user could paste text that would get inserted. This commit prevents that by ignoring `paste` events when selection is in a `contenteditable=false`. Steps to reproduce: - On `form/help-1`, open website builder - Select the text of "Help" title - Paste text - Bug: text is inserted task-4367641 Forward-Port-Of: odoo/odoo#228149
This fix makes an automated test for signed document cleanup reliable by avoiding timing edge cases around deletion dates. It helps prevent false test failures without changing how users work with documents.
Original PR description
Steps to reproduce
==================
Launch the test `test_gc_clear_bin` a few times
It will eventually fail:
documents.document(544,) is not false :
trash document should be deleted after gc_clear_bin
Cause of the issue
==================
The domain for wether a record should be deleted contains `('write_date', '<=', fields.Datetime.now() - relativedelta(days=deletion_delay)`
The tests fails when the write_date is in the same second as the test run.
This is because fields.Datetime.now() replaces microseconds by 0.
https://github.com/odoo/odoo/blob/14073faf1fa272b8d3411b4fe6f42c279058459d/odoo/fields.py#L2378
Solution
========
Since records needs to be at least "deletion_delay" old, we add a margin of 30 seconds to make sure they match
runbot-224207
Forward-Port-Of: odoo/enterprise#95926A test setup for Peruvian electronic invoicing now gives the test user the needed sales permission when demo data is disabled. This prevents false test failures and helps keep invoicing quality checks reliable.
Original PR description
Issue: - user is missing a group to create sale order for `test_invoice_down_payment_foreign_currency` without demo data Step to reproduce - run odoo enterprise with : `-i sale,l10n_pe_edi --without-demo=True --test-tags test_invoice_down_payment_foreign_currency` Solution: - add corresponding group to user related [to PR](https://github.com/odoo/enterprise/pull/93885) runbot-233038
Moving an opportunity into an empty CRM pipeline stage no longer triggers an error when recurring revenue is enabled. This keeps the sales pipeline usable and prevents interruptions during normal drag-and-drop work.
Original PR description
**Steps to reproduce:** 1.Install crm 2.Enable 'Recurring Revenues' from settings 3.Go to CRM > 'My pipeline' > Create a record here 4.Enable debug mode 5.Either create a new stage or move records from any stage to make an empty stage 6.Move created record to an empty stage **Issue:** This Traceback accurs : "Uncaught Promise > Invalid props for component 'AnimatedNumber': 'value' is not a number" **Cause:** https://github.com/odoo/odoo/blob/5ade756227abf58769ff904651628a3ccaf8e19a/addons/web/static/src/views/view_components/animated_number.js#L8-L21 AnimatedNumber expects a numeric value for its value prop. When moving to an empty stage, the aggregate value is false, which is not a valid number for the component. **Solution:** Check for the rrmAggregate value to render the component. opw-4972672
Users can now open the overview for completed manufacturing orders even when no bill of materials is linked. This prevents an erroneous unit-of-measure error and helps teams review production records without interruption.
Original PR description
Steps to reproduce: - Create a storable product “P1” - Create a manufacturing order to produce one unit of P1: - add any component - Mark the MO as done - Try to open the MO overview Issue: An error is raised because the MO has no BoM. But in the function we try to compute the missing quantity in the BoM's UoM, but since no BoM is linked, there is no UoM available. Error message: "The unit of measure Unit defined on the order line doesn't belong to the same category as the unit of measure %(product_unit)s defined on the product. Please correct the unit of measure defined on the order line or on the product. They should belong to the same category." Fix: Skip the computation of missing BoM quantities when no BoM is linked, allowing the MO overview to be opened without error. opw-5112132 Opw-5105544 Opw-5119897 Forward-Port-Of: odoo/odoo#229707
This fix ensures manufacturing shop floor screens handle removed BoM components without showing duplicate material lines or crashing. It adds test coverage so the issue does not return, helping operators continue work smoothly after production setup changes.
Original PR description
### Steps to reproduce: 1. Create a BoM with two components to be consumed in an operation 2. Create a Manufacturing Order with this BoM and confirm it 3. On the BoM, remove one of the products and save 4. Go to the Shop Floor 5. Select the workcenter used in step 1 6. Got duplicate key in t-foreach ### Before this commit: Stock moves without quality checks, that are linked to a workorder but not linked to a BoM line, are included twice in the view, resulting into a traceback. ### After this commit: Include only once the stock moves, removing duplicates from the view. opw-5029970 Forward-Port-Of: odoo/enterprise#93482
This change fixes an unreliable automated test for bus notifications that could fail randomly depending on how notification batches were read. It helps keep the release process stable by ensuring the test checks all received notifications instead of accidentally ignoring some.
Original PR description
This commit fixes the `test_postcommit` that fails in a non deterministic fashion. This test ensures bus notifications created in the post commit hook result in only one batch. However, the listener only consider the first notification of the batch (`conn.notifies.pop()`) and ignore the rest. When the expected notifications come as part of a bigger batch, they can be ignored thus making the test fail. This commit ensures we read every notification received. fixes runbot-233185 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#230117 Forward-Port-Of: odoo/odoo#230054
This fixes an issue where certain remote procedure calls could fail when request parameters used names that conflicted with internal fields such as model or method. The change improves reliability for integrations and web requests without changing user workflows.
Original PR description
Backport of odoo/odoo#227801 in saas-18.4 X-Original-Commit: 1bb69de64165b18fca7d00164c5299e58c48d40f