Wednesday, August 27, 2025
13 changes · 18.0
Resolved issues and error corrections
Manufacturing orders created from sales for products with an empty bill of materials now stay in draft instead of being automatically confirmed. This prevents users from ending up with confirmed orders that have nothing to produce or track, giving them time to add any needed details first.
Original PR description
Issue Before This Commit: ============================ Currently, if a BOM has `no components or operations` and is triggered via `MTSO`, the generated Manufacturing Order (MO) is automatically set to a `confirmed` state. This behaviour is inconsistent and not meaningful, as there's nothing to produce or track. Steps to Reproduce: ============================ - Install the `mrp and sale` module. - Enable MTSO route. - Create a product with a BOM that has `no components or operations`. - Create a sale order for that product. MO is created in a `confirmed` state. With This Commit: ============================ This commit ensures that MOs triggered via `MTO(Already worked) or MTSO` are created in draft state if their BOM has no components and no operations. This allows the user to manually add required details before confirming the MO. supporting custom use cases. TaskID:- 4920195
Fixes form save warnings so they can open the intended follow-up action with the correct extra information. This helps users resolve save-blocking issues directly from the warning instead of being left in a broken or incomplete flow.
Original PR description
Have a web_save that raises a RedirectWarning which has the ID of an action and an additional context in its parameters. Trigger the warning in the form view by clicking on the save button in the form view. Before this commit, this feature did not work like at all. - The additional context was not taken into account - the path taken by clicking on the form's save button was not able to handle interacting with the main form view - The error dialog did not handle going into an action in target other than new After this commit, all this is fixed and the whole flow, that allow an error to be enriched such that the user could do the correct action to correct the error now works. opw-4742952 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#223198
Fixed an issue in Point of Sale restaurants where combo items could lose their link to the main combo product after table synchronization. This helps ensure orders remain accurate and easier for staff to manage when customers or order details are updated.
Original PR description
When one of the combo line is marked as "Dirty", it would be synched but it would remove it's link to the combo parent. Steps to reproduce: ------------------- * Create a combo product * Open a PoS restaurant * Open a table, and add the combo product * Leave the table to synchronize the order with the backend * Go back on the table and select a partner * This will mark the combo line as "dirty" * Leave the table again to synchronize the order with the backend * Go back on the table > Observation: The combo now appears as a normal product, not linked to the combo parent. Why the fix: ------------ When marking a line as "dirty", we now make sure to also mark it's combo parent as "dirty" so that it will be synchronized correctly. And keep the link to the combo parent. opw-4950262
Fixes an error that could interrupt users editing a sales order when multiple linked invoices are shown on the form. This makes the sales order editing experience more reliable for customers using Studio customizations with invoice information.
Original PR description
**Step to reproduce** - create a SO - link 2+ invoices to it - using studio, add invoice_ids to the SO Form - trigger a onchange (ex. change the product from SOL) - we receive a traceback…
**Step to reproduce** - create a SO - link 2+ invoices to it - using studio, add invoice_ids to the SO Form - trigger a onchange (ex. change the product from SOL) - we receive a traceback **Traceback:** ```ValueError: Expected singleton: account.move(<NewId origin=35>, <NewId origin=31>, <NewId origin=32>, <NewId origin=33>, <NewId origin=34>)``` **Issue:** - from `onchange` triggers chain,`_compute_duplicated_ref_ids` is invoked calling `_fetch_duplicate_reference` for the related moves (invoice_ids) such that as they are in create/edit mode - at this time `convert_to_write(moves[field_name], moves)` fails as moves has more than 1 record and `recordset[field]` is not valid syntax in such case https://github.com/odoo/odoo/blob/3966753eb5a8534c8b5b8a16e626f5250c9013cf/addons/account/models/account_move.py#L1868-L1884 - hence, we receive valueError, expecting a singleton **Fix;** - we adapt the method to accept multiple moves which may be in create/edit mode opw-4959528 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where older point-of-sale refunds that combined items from multiple original orders could fail after upgrading. Businesses can now view those refund orders and complete upgrades without this data compatibility error blocking the process.
Original PR description
In saas~17.1, the field `refunded_order_id` was changed from a Many2Many to a Many2One, as refunding lines from different orders with the same order was no longer possible. The problem is that there were no changes applied to the existing data to account for this, so databases with those kind of refunds will trigger an error when the field is computed: ``` ValueError: Wrong value for pos.order.refunded_order_id ``` This behaviour can also break upgrades if the error happens during the mock crawl test after the upgrade. To reproduce: - In 17, create an order refunding products from different orders. - Upgrade to 18. - Try to view the refunding order. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Submitting a website “Send Email” form without a recipient email now avoids an error that previously blocked the form. This makes website forms more reliable for users configuring email actions through the website editor.
Original PR description
Currently, an error occurs when submitting the 'Send Email' form. **Steps to Reproduce:** - Install the `website` and `web_studio` modules. - Go to `website` > Click on `Edit` > `Drag and drop form`.…
Currently, an error occurs when submitting the 'Send Email' form. **Steps to Reproduce:** - Install the `website` and `web_studio` modules. - Go to `website` > Click on `Edit` > `Drag and drop form`. - Click the `form` and in `Actions` select the `more models`, and select `outgoing mails(mail.mail)` model and `save`. - Fill out the form and `Submit`. **Error:** `KeyError: 'website_form_signature'` **Cause:** This error occurs after [this commit](https://github.com/odoo/odoo/commit/70fa5af872524ea271113851c050297ef50efa45), when submitting the "Send Email" form from the website. If the form is saved without entering the recipient's email (email_to). As a result, the `email_to` field is not present in the form. The `website_form_signature` is added from [1], but due to the condition at [2], the code at [1] is not executed. And when it is accessed at [3], KeyError is raised. [1]: https://github.com/odoo/odoo/blob/82639728f2bcb4e7786f120de2aeba3f5fbab209/addons/website/tools.py#L252 [2]: https://github.com/odoo/odoo/blob/82639728f2bcb4e7786f120de2aeba3f5fbab209/addons/website/tools.py#L236 [3]: https://github.com/odoo/odoo/blob/82639728f2bcb4e7786f120de2aeba3f5fbab209/addons/website/controllers/form.py#L88 **Fix:** This commit ensures that 'website_form_signature' is used if it is available in kwargs. sentry-6746753251 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The debug Data view no longer crashes when a record includes custom property fields. This helps administrators and support teams inspect record information reliably during troubleshooting, including in CRM forms with added property fields.
Original PR description
Example Steps: - Install `crm` - Add a random field properties in a random form view - Enable debug mode - Open debug menu - Select Data - Traceback ```py raise ValueError(f"Invalid field…
Example Steps:
- Install `crm`
- Add a random field properties in a random form view
- Enable debug mode
- Open debug menu
- Select Data
- Traceback
```py
raise ValueError(f"Invalid field {field_name!r} on model {self._name!r}")
ValueError: Invalid field 'properties.xyz' on model 'x.y'
```
There are two causes for this problem.
First, we use orm.read to retrieve data from records, which does not directly handle sub-field properties. We only need to use `definition_property` (which contains the overall schema of the JSON field).
Second, when displaying the data, we use JSON.stringify with `replacer`:
```js
get content() {
const record = this.props.record;
return JSON.stringify(record, Object.keys(record).sort(), 2);
}
```
In this case, replace contains all the keys present in record, sorted. The problem is that the properties fields are themselves objects that contain the keys: `name`, `string`, `type`, `default`, `value`.
And giving an array to replace in `JSON.stringify` will filter the keys and keep only those that are whitelisted in it.
```js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
const foo = {
foundation: “Mozilla”,
model: “box”,
week: 45,
transport: “car”,
month: 7,
};
JSON.stringify(foo, [“week”, “month”]);
// ‘{“week”:45,“month”:7}’, only keep ‘week’ and “month” properties
```
This will ignore the keys of the properties fields.
The fix is therefore to sort the object before stringifying it, without using replace.
Thanks to these two fixes, the data is displayed as expected, regardless of whether there are field properties or not.
opw-5017425This fix prevents errors and unwanted visual effects when website blocks use both gradient and image backgrounds. Users can now switch image display modes such as repeat pattern or parallax without causing console errors or making gradients repeat incorrectly.
Original PR description
*=website Target: 17.0 to saas-18.3 Issue: This issue applies to any block where multiple backgrounds are present (gradient + image). Steps to Reproduce: 1. Drop a masonry snippet onto the page. 2.…
*=website Target: 17.0 to saas-18.3 Issue: This issue applies to any block where multiple backgrounds are present (gradient + image). Steps to Reproduce: 1. Drop a masonry snippet onto the page. 2. Select a block and change the background color to the gradient. 3. Add background image. 3. Change the image position from "Cover" to "Repeat Pattern." 4. Observe the traceback in the console. Reason: The issue occurred due to incorrect parsing of CSS background values when multiple background layers were applied (e.g., a gradient + image). When both are set, the element ends up with multiple background-related properties. Previously, In setValue method, Inside MultiUserValueWidget when value = "100px, 100px", the resulting values array was ['100px,', '100px'], which included an extra comma. This has now been corrected to properly handle such cases. Other edge cases fixed: 1. Gradient was repeating along with the image. 2. Switching to parallax after repeat-pattern causes gradient to repeat. 3. Removing image kept repeat class, causing gradient to repeat. Fix Summary: 1. We updated `selectStyle` and _computeWidgetState to correctly handle multi-layer background-size and repeat styles. In selectStyle, we set the height and width values from options and apply them only to the image layer (not gradient), keeping the gradient layer unchanged. In `_computeWidgetState`, we fetch the background-size from the target and, if multiple layers are present, return only the first one (image layer), since height and width options apply only to that. Now, setValue receives only single-layer values like `100px 50px`, ensuring correct behavior. Set background-size 'cover' to gradient which ensures only the image repeats while the gradient remains fixed. 2. Remove `o_bg_img_opt_repeat` and reset background-size when - Image is removed. - Switching to parallax. task-4577864 Forward-Port-Of: odoo/odoo#207757
Stopping a timesheet timer now uses the user's local date instead of UTC when matching entries. This prevents time from being added to the previous or next day for users working across time zones.
Original PR description
Before this commit, if you were to log time on a timesheet using the timer start and stop buttons, you could potentially log time for the previous day's or the upcoming day's timesheet entry. This is because we were searching for previously-created timesheet entries based on the UTC Date of the timer's "stop" time. This fix uses the client's local time to get the Date of the timer stop. With this, we'll only find timesheet entries with the `date` field matching the client's local Date. opw-4967487 Forward-Port-Of: odoo/enterprise#93010 Forward-Port-Of: odoo/enterprise#92569
Planning notification emails now send portal users to the correct planning page instead of the general portal dashboard. This helps external users access their published shifts 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
Rental orders settled through Point of Sale now keep the delivered quantity accurate when items are returned. This prevents returned rental products from being counted as delivered more than once, improving order accuracy and reducing manual corrections.
Original PR description
**Issue:** Before this commit, the qty_delivered was wrong when using the Return button when a Picking was made in PoS **Cause:** The `_compute_qty_delivered` method in `pos_sale` adds `pos_line.qty`…
**Issue:** Before this commit, the qty_delivered was wrong when using the Return button when a Picking was made in PoS **Cause:** The `_compute_qty_delivered` method in `pos_sale` adds `pos_line.qty` to the related `sale_line` each time it runs When there is no PoS order, the method add 0 to the line, so the expected behavior work But when you have a PoS Picking, a quantity was added to `qty_delivered` each time the `rental.order.wizard` is used The issue also occured earlier when the `flush_all()` is called in `_process_order()` **Fix:** There is already a `_compute_qty_delivered` method in `pos_sale_stock_renting` that override the `qty_delivered` But it's restricted by `_are_rental_pickings_enabled()` That's not necessary because we don't use any `stock.picking` in the `_compute_qty_delivered` function, only `stock.move` so we removed that verification To make the code working, we also need to extend the _get_outgoing_incoming_moves() results Because there were also block by a `_are_rental_pickings_enabled()` condition even if there is only moves here We need all the moves to calculate `qty_delivered` properly **Steps to reproduce:** - Create a New Product "Rental PoS" that Can be Rented - Create and confirm a New Rental Order, with any customer and your product - Open a PoS Session - Click on Quotation/Order - Choose the last Order and Settle the order - Click on Yes (to confirm import to PoS) - Click on Payment, select Cash and Pay - Go in the Backend, and to your RO - Click Return and Validate - Before the fix, the Delivered should be 2.0 opw-4877019 Forward-Port-Of: odoo/enterprise#90510
Refreshing a document that was sent for signature no longer causes an error. The signing page now keeps the needed document state in the URL so users can reload the page without losing access or interrupting their workflow.
Original PR description
Version: - 18.0 Steps to reproduce: - Open document which is send for signature. - Refresh the browser. Before: - Refreshing the page caused a traceback error. - The requestItemStates value was loaded from the context, which is only available when navigating from go_to_document. - On refresh, the context was lost, leading to the error. After: - Added requestItemStates to the URL query string. - On page refresh, the data is retrieved from the URL as a fallback instead of relying on the context. Impact: - Fixes the error that occurred on page refresh. - Ensures a smoother and more stable user experience when viewing documents. task-4805166
Brazilian invoices using Avalara no longer add exempt ICMS taxes as extra journal item amounts when Avalara marks them as not accounting-relevant. This prevents invoice totals from being overstated while still keeping a visible record of the ignored tax in the invoice chatter.
Original PR description
### Steps to reproduce:
- Install l10n_br_edi, switch to Brazilian company
- Set up Avalara
- Create an invoice with the tax "ICMS Exemption Incl." which is included in price
- Click "Generate taxes" to compute the taxes with Avalara
- In "Journal Items" we can see a line for "ICMS Exemption Incl.", its value appear as excluded
### Cause:
The result from Avalara included a value for this tax:
```
'tax': 1.44,
'taxImpact': {
'accounting': 'none',
'impactOnFinalPrice': 'Included',
'impactOnNetAmount': 'Included',
},
```
But the untaxed amount is computed without this tax. Odoo keeps the untaxed amount from the response and add a line for the tax. As a result the tax is added to the amounts like an excluded tax would.
### Solution:
In the response from Avalara, we don't want to create a line for the tax `icmsDeson` when there is `'accounting': 'none'`.
We also log this tax in the chatter to keep a trace of it.
opw-4964315