Friday, April 24, 2026
31 changes · saas-19.2
Resolved issues and error corrections
This update resolves a problem where confirming deliveries for kit products would trigger errors. The fix prevents unnecessary move explosions during delivery validation, ensuring deliveries can be confirmed smoothly. This prevents potential issues with stock valuation.
Original PR description
**Issue**: Making a product a kit could prevent confirming deliveries. **Steps to reproduce**: - Make sure the account application is installed - Create a product P without kit - Create a SO and…
**Issue**: Making a product a kit could prevent confirming deliveries. **Steps to reproduce**: - Make sure the account application is installed - Create a product P without kit - Create a SO and confirm it - Make the product P a kit - Validate the delivery associated to the SO -> A traceback occurs: the record does not exist anymore **Cause**: While confirming the delivery: https://github.com/odoo/odoo/blob/a253cff9039fcf729a9922b119acad5ec7c7a0bd/addons/stock_account/models/stock_move.py#L168 It first filters which moves are out (`moves_out`). On the move associated with product P, since the kit is not exploded yet: https://github.com/odoo/odoo/blob/a253cff9039fcf729a9922b119acad5ec7c7a0bd/addons/stock_account/models/stock_move.py#L172 Then explodes the kit: https://github.com/odoo/odoo/blob/a253cff9039fcf729a9922b119acad5ec7c7a0bd/addons/stock_account/models/stock_move.py#L174 https://github.com/odoo/odoo/blob/ea18f34a48d61350f80c79894bef66bf02840bfc/addons/mrp/models/stock_move.py#L357-L361 By doing so, the original move associated to the product P are deleted: https://github.com/odoo/odoo/blob/ea18f34a48d61350f80c79894bef66bf02840bfc/addons/mrp/models/stock_move.py#L399 Thus, `moves_out` contains moves that no longer exist, and eventually, and eventually while accessing `product_id`: https://github.com/odoo/odoo/blob/a253cff9039fcf729a9922b119acad5ec7c7a0bd/addons/stock_account/models/stock_move.py#L179 A traceback is thrown **Aditionnal information** Validating a delivery of a kit product whose moves were not exploded will trigger their explosion and require a second validation. Therefore, no stock valuation errors will be created. opw-6063602 Forward-Port-Of: odoo/odoo#258403
This update fixes an issue where invoices generated from KSeF bills weren't correctly processing gross unit prices. The system now supports both net and gross unit price reporting from vendors, ensuring accurate invoice generation and compliance with Polish tax regulations. This prevents incorrect invoices and potential financial discrepancies.
Original PR description
**PROBLEM** When receiving bills from KSeF, we don't handle gross unit price and default to a price_unit of 0.0. Leading to an incorrect invoice. When generating the bill, the vendor can choose to report the net unit price (P_9A) or gross unit price (P_9B). We need to handle both cases. opw-6066027 Forward-Port-Of: odoo/odoo#260314
This update resolves a bug in the overtime calculation process for employees with specific attendance records. The fix ensures that overtime calculations are accurate, particularly when employees' attendance times involve midnight transitions. This prevents errors and ensures correct overtime payments.
Original PR description
**Context** - "Absence Management" is enabled in the database settings - Employee has an overtime ruleset selected in their employee settings - That overtime ruleset has a rule with a non-zero `expected_hours` - That employee has 1 or more attendance records that start or end at midnight in their timezone. **Before this commit** When updating overtime records, either via the "Regenerate overtimes" button on the overtime rule, or by simply creating a new attendance record, we'll end up passing around an intervals object that contains no intervals. Then, when we later assume this object will have at least one element, we crash. **After this commit** Guarantee that intervals objects are populated before assuming they are. Further, we remove the opportunity to create an empty intervals object that was exposing this bug. opw-6035270 Forward-Port-Of: odoo/odoo#260772 Forward-Port-Of: odoo/odoo#257986
This update resolves a reporting discrepancy where planned hours were incorrectly shown for public holidays. The fix ensures the system accurately excludes public holidays, regardless of whether they're linked to a specific calendar, and accounts for timezone differences to prevent date shifting issues. This improves the accuracy of timesheet forecasts.
Original PR description
### Steps to reproduce: - Install project_timesheet_forecast module - Configure your database to have a far timezone (Montevideo/Uruguay in my case) - Create a public holiday starts from 12AM to…
### Steps to reproduce: - Install project_timesheet_forecast module - Configure your database to have a far timezone (Montevideo/Uruguay in my case) - Create a public holiday starts from 12AM to 11:59PM with a calendar - Create a planning slot for a resource that overlap with the public holiday - Check the Timesheets / Planning analysis report - Group by employees > day **- Check the date of the public holiday and notice there are still planned hours shown** - Remove the calendar from the public holidays that we created previously - Check the report once again **- Notice the day of the public holiday and the day after has no planned hours** ### Cause: In the query we are using to exclude the leave days from the report we only exclude the ones that has calendar_id assigned, not taking into consideration that some of the public holiday are general and is not applied to just one working schedule. Also if we have a leave starting midnight to 11:59PM since we store dates in database as UTC for timezone like Uruguay's one it will shift the end with one day which will introduce inconsistencies ### Fix: We check if the calendar_id is null on the resource_calendar_leaves and make sure we take timezone of the resource into account when checking the dates of the leaves. opw-5027070 Forward-Port-Of: odoo/enterprise#111846
This update ensures that links within documents added to the website builder – whether through the `/file` command or replacing media like images – are correctly translated inline. Previously, a different upload process didn't apply the necessary translation, leading to broken links. This fix resolves this inconsistency and improves the user experience for adding and managing documents on the website.
Original PR description
[FIX] website: translate links inline on media replacement On the website builder, files added through the `/file` command would go through the domPlugin `insert` method, which would call…
[FIX] website: translate links inline on media replacement
On the website builder, files added through the `/file` command would go
through the domPlugin `insert` method, which would call
`before_insert_processors` and apply `.o_translate_inline` as expected.
But there is another flow to add a document on the page: replace an
image (or video, or icon), then select the "Documents" tab and upload
a file. With this flow, `insert` is not called, so we have to add the
class through some other resource.
[FIX] html_editor: target documents with right class
The class `.o_image` was still associated with documents (in the context
of the file selector) and the expected tag of a document was `A`, in
spite of it not being true in `html_editor` since the introduction of
the file box in [1].
This has also been updated in the website builder since the introduction
of the `html_builder` module in 18.4, which swapped uses of `web_editor`
components for `html_editor`.
As a side-effect, in website, a double click on a file did not open the
media dialog on the "document" tab, unlike other media (images, videos,
icons). In such a case, the file was also not shown as already selected
in the media dialog (because it targetted the wrong tag name). Both of
those behaviors were lost as we used the new file box design in 18.4.
[1]: https://github.com/odoo/odoo/commit/7f9afa21dffba2f74f9fb8a68809db4af6c7c225
task-5876278
Forward-Port-Of: odoo/odoo#259840
Forward-Port-Of: odoo/odoo#245904This update fixes a bug where the shipping address wasn't appearing on Purchase Order (PO) and Request for Quotation (RFQ) reports. The change involves updating how address information is passed within the Odoo reporting system, ensuring that customer shipping details are now correctly displayed. This improves the accuracy of purchase order data.
Original PR description
Version: ---------- - saas-19.2+ Steps to reproduce: ---------------------- 1. Install `stock_dropshipping` and `sale_management` modules. 2. Create a Customer (res.partner) with a proper address…
Version:
----------
- saas-19.2+
Steps to reproduce:
----------------------
1. Install `stock_dropshipping` and `sale_management` modules.
2. Create a Customer (res.partner) with a proper address block.
3. Create a dropship product (route: Dropship).
4. Create a Sales Order for the created customer.
5. Add the dropship product.
6. Confirm the Sales Order to generate a Purchase Order.
7. Open the generated PO/RFQ and print the report.
Issue:
------
The shipping address is missing in the printed PO/RFQ report.
Cause:
--------
The `t-call` syntax is updated to use the new semantic, which passes
values *as attributes/parameters* on the `<t>` (with `t-call`) tag itself,
instead of relying on nested `t-set` directive.
- Old (Deprecated): Used nested `<t t-set='var_name' t-value='x'/>` tags
inside the calling element to define variables.
- New: Variables are passed as attributes directly on the element where
the `t-call` is located (e.g., `<t t-call='module.template' var_name='x'/>`).
A warning is added to alert developers when using the old deprecated
syntax.
see Reference: https://github.com/odoo/odoo/pull/197296
<details>
<summary>Click here to see the results:</summary>
<p><strong>Before:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/c6892b30-10d6-4fb4-881c-1433d4fe07a0" />
</div>
<p><strong>After:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/6109fcc3-5773-44a8-b07b-6566ed855d3f" />
</div>
</details>
> NOTE: We can also move test into `purchase_stock`
----
opw-6075017
---
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-prThis update fixes a confusing issue for Mexican employees receiving payslips. Previously, an unstamped payslip was emailed immediately after batch confirmation, followed by a second email with the stamped version. Now, the email is only sent when the CFDI (tax document) is generated, ensuring employees receive the correct, fully stamped payslip.
Original PR description
Currently, when a user confirms a payslip batch (hr.payslip.run), the base payroll module queues the PDF generation and sends an email to the employee with their payslip immediately. For Mexican payslips, this means the employee receives the email with an unstamped payslip (without CFDI UUID). Later, when the CFDI is generated, a second email is sent with the stamped version, confusing the employee. This commit prevents the email from being sent for Mexican payslips if the CFDI has not been generated yet, ensuring only the stamped payslip is emailed. Forward-Port-Of: odoo/enterprise#114731
This update fixes an issue where the unit cost of tracked products with consigned quantities was incorrectly calculated. The change ensures that consigned quantities are excluded from the unit cost calculation, resulting in accurate valuation for products with partial ownership. This improves inventory reporting accuracy.
Original PR description
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco…
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco product with a cost of 10 - click on the quantities smart button and then "update quantity" to open the quants view - create one line with a quantity of 1 and no owner - create one line with a quantity of 1 and an owner outside the company **Current behavior:** problem A: open the 'stock' view and look for your product, the unit cost is 5 problem B: navigate back to the quants view of the product, unhide the value column, the value is 5 for the non consigned quant **Expected behavior:** problem A: the unit cost should be 10 (because consigned product shouldn't be taken into account when computing the unit cost) problem B: the non consigned quant value should be 10 for the same reason **Cause of the issue:** problem A: Inside _compute_value(), to compute total_value_by_company_id, we use _with_valuation_context() https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L196-L203 which excludes consigned products https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L362-L364 So when we iterate through 'products' and fetch qty_available for our product the value is going to be 1. But when computing avg_cost at the end of the method, we iterate through 'self', so we don't have this context anymore and the value of qty_available is 2. https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L271-L273 That's because qty_available is computed with _compute_quantities() which depends on context (including owner_id) https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock/models/product.py#L148-L152 problem B: when computing the value of the quant, there is no context specifying that the consigned quantities should be excluded https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock_account/models/stock_quant.py#L61-L62 opw-6049413 Forward-Port-Of: odoo/odoo#257013
This update fixes an issue where VAT reports incorrectly used the company's VAT number instead of the fiscal position's foreign VAT ID. The change ensures that VAT reports accurately reflect the correct tax identification number for each country, improving tax reporting accuracy. This resolves a discrepancy impacting financial reporting.
Original PR description
### Issue: When a fiscal position defines a `foreign_vat`, tax reports generated for that country still use the company's VAT number instead For example, with a Belgian fiscal position using…
### Issue: When a fiscal position defines a `foreign_vat`, tax reports generated for that country still use the company's VAT number instead For example, with a Belgian fiscal position using `BE010203040`, the generated BE VAT report uses the company VAT instead of `010203040` ### Cause: The report generation did not check whether there is a fiscal position with a `foreign_vat` matching the country of the report ### Note: The example above uses a Belgian fiscal position to reproduce the issue Starting from 19.0, this specific flow is blocked because Intervat is enabled in production mode by default A related fix makes the Intervat settings available in that case Until then, the issue can be reproduced by temporarily commenting out: https://github.com/odoo/enterprise/blob/5fb58a9b7b3ae89f87e84d4ba1fa3a16237d80ac/l10n_be_intervat/models/account_return.py#L15 ### Steps to reproduce: - Disable demo data and install `accountant` - Create a Fiscal Position "Belgium" (Country: Belgium, Foreign Tax ID: BE010203040) - Click the alert to install the Belgian taxes - Create and confirm an invoice for a Belgian customer: - Fiscal Position: Belgium - Any product with a Belgian tax - Invoice Date: 01/01/2026 - Open the Tax Report and select `VAT Return (BE)` for January - Click `Returns` and select the full year - Mark the December return as Completed from the three-dot menu - Review January and fill the missing company data (TIN: 1111111, phone and email) - Click `Validate -> Lock -> Submit` ### Before the fix: The generated XML uses the company VAT number (`1111111`) instead of the fiscal position foreign VAT (`010203040`). opw-6076540 Forward-Port-Of: odoo/enterprise#112610
This update addresses a critical issue where Odoo Enterprise experienced a crash when attempting to download a URL document alongside a spreadsheet. The fix ensures stable and reliable downloading of both document types, improving user experience and preventing data loss. This resolves a reported problem impacting users accessing and sharing documents.
Original PR description
Try to download a url document along with a spreadsheet. `onDownload` crash when trying to download a url document. Task: 5485662 Forward-Port-Of: odoo/enterprise#113645 Forward-Port-Of: odoo/enterprise#112513
This update fixes an issue where car BIK calculations were inaccurate when employees changed cars during a month. The system now correctly prorates the BIK based on the employee's car usage each month, ensuring accurate payroll calculations and compliance. This change impacts the HR payroll module.
Original PR description
**Description of the issue/feature this PR addresses:** When there is a change of car during a month, the employee will have 2 versions but all will be merged on the same payslips but currently only the BIK of one version is taken into account (or no BIK if the employee has no company car anymore) **Current behavior before PR:** . car_atn value equal the yearly_atn / 12 . ATN.CAR rule returns the car_atn value of the first version **Desired behavior after PR is merged:** . Update the car_atn value to be computed monthly, based on the number of calendar days in the current month . Update ATN.CAR payslip rule, it get the value of the car's atn on the current payslip month then prorated based on the versions periods within the payslip period . Modify the corresponding tests . Add corresponding tests task-6108696
This update resolves an issue where the Odoo system couldn't correctly handle the Turkey timezone after a recent software update. The fix adds a fallback mechanism to ensure accurate timezone calculations, preventing errors during database upgrades and ensuring correct event scheduling.
Original PR description
**[FIX] handle Turkey timezone when tzdata-legacy not installed** In #236660 we switched from pytz to zoneinfo. The library `pytz` has `Turkey` in **pytz.all_timezones_set**. On the other hand…
**[FIX] handle Turkey timezone when tzdata-legacy not installed**
In #236660 we switched from pytz to zoneinfo.
The library `pytz` has `Turkey` in **pytz.all_timezones_set**.
On the other hand starting from ubuntu 24.04 as tzdata was split and `Turkey` was [moved](https://documentation.ubuntu.com/release-notes/24.04/#tzdata-package-split) out of tzdata to tzdata-legacy.
If we run a db which has reference to `Turkey` timezone, on a server which is ubuntu 24.04 and tzdata-legacy not installed, we will get an error as we did not have fallback for `Turkey` while we have for `Türkiye`. Because zoneinfo will not have `Turkey` in `zoneinfo.available_timezones()`
Issue was discovered during upgrade of db which has res.partners with timezone=`Turkey` from 19.0 to saas~19.1. The upgrading docker container was nobel and it did not have tzdata-legacy.
For fixing the issue we added fallback for `Turkey`.
Tbh I do not think we need a fallback for `Türkiye` but I wanted to not change the old behaviour.
###
**[FIX] handle America/{Catamarca,Godthab} timezones**
As we moved from `pytz` to `zoneinfo` in **saas~19.1**
we have 2 more timezones which were existing in `pytz`
but not in `tzdata` adn we do not have fallback for them.
They are in `tzdata-legacy`:
- America/Catamarca
- America/Godthab
We added fallback for them.
We already have a failing upgrade request because of
America/Catamarca.
Turkey:
```
File "/home/odoo/src/odoo/saas-19.1/addons/calendar/models/calendar_event.py", line 742, in _compute_field_value
return super()._compute_field_value(field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/addons/mail/models/mail_thread.py", line 495, in _compute_field_value
return super()._compute_field_value(field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/models.py", line 4271, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/fields.py", line 83, in determine
return needle(*args)
^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/addons/calendar/models/calendar_event.py", line 503, in _compute_recurrence
event_values = event._get_recurrence_params()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/addons/calendar/models/calendar_event.py", line 1341, in _get_recurrence_params
event_date = self._get_start_date()
^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/addons/calendar/models/calendar_event.py", line 1573, in _get_start_date
return start.replace(tzinfo=UTC).astimezone(ZoneInfo(self.event_tz)).date()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/_monkeypatches/zoneinfo.py", line 130, in __new__
z = super().__new__(cls, key)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/zoneinfo/_common.py", line 24, in load_tzdata
raise ZoneInfoNotFoundError(f"No time zone found with key {key}")
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key Turkey'
```
Catamarca:
```
Traceback (most recent call last):
File "/tmp/tmpm0v0h90i/migrations/base/tests/test_mock_crawl.py", line 335, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpm0v0h90i/migrations/base/tests/test_mock_crawl.py", line 348, in mock_action
return self.mock_act_window(action)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/tmpm0v0h90i/migrations/base/tests/test_mock_crawl.py", line 508, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpm0v0h90i/migrations/base/tests/test_mock_crawl.py", line 541, in mock_view_form
[data] = record.read(fields_list)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/models.py", line 2735, in read
self._origin.fetch(fields)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/models.py", line 3067, in fetch
fetched.mapped(field_name)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/models.py", line 5479, in mapped
return [getter(record) for record in records]
^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/fields.py", line 1794, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/fields.py", line 1965, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/models.py", line 4271, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/saas-19.1/odoo/orm/fields.py", line 83, in determine
return needle(*args)
^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/addons/base/models/res_users.py", line 455, in _compute_tz_offset
user.tz_offset = datetime.datetime.now(ZoneInfo(user.tz or 'UTC')).strftime('%z')
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.1/odoo/_monkeypatches/zoneinfo.py", line 130, in __new__
z = super().__new__(cls, key)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/zoneinfo/_common.py", line 24, in load_tzdata
raise ZoneInfoNotFoundError(f"No time zone found with key {key}")
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key America/Catamarca'
```
tbg-2529
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#256821This update resolves an issue where deleting a button in the HTML editor would unexpectedly remove the entire editor. The fix ensures that after deleting a button, the editor correctly recognizes the empty space and adds a line break, preventing the editor from being removed entirely. This improves the user experience and stability of the HTML editor.
Original PR description
### Steps to reproduce: - Create a button, set its URL to #, and click Apply. - Place the cursor right after the link. - Press Backspace until the button/link is removed. - Entire editor also gets…
### Steps to reproduce: - Create a button, set its URL to #, and click Apply. - Place the cursor right after the link. - Press Backspace until the button/link is removed. - Entire editor also gets removed. ### In previous version: - Issue is due to [1](https://github.com/odoo/odoo/commit/7685e562b1036d08724ba91ed5064b6fe20c2ce2 ) change in `isEmptyBlock` (because of `isButton`). - When we had `<a>#[]</a>` and pressed backspace, `deleteRange` was called. - Then `fillShrunkBlocks` ran and `isEmptyBlock` returned true (no isButton). - So `<br>` was added and block never became fully empty. ### In current version: - Because of `isButton` condition, some empty blocks are not treated as empty. - So `<br>` is not added & block stays actually empty. Then `removeFEFF` runs & `nodeSize` becomes false & `cleanEmptyAncestors` removes parent even editable. ### After this PR: - Case like `<a>[]</a>`, backspace is handled by override which directly removes `<a>`. Since this skips `deleteRange`, manually call `fillShrunkBlocks` there. - Now after removing `<a>`, block is properly detected as empty and `<br>` gets added. task-6109145 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259055
This update resolves a migration issue by requiring the ‘survey’ module to be installed before the ‘esg_csrd’ module can be automatically updated. Previously, users without ‘survey’ would incorrectly install it, leading to migration problems. Now, the update only proceeds if the ‘survey’ module is already present, ensuring a stable and reliable migration process.
Original PR description
Description of the issue this commit addresses: As survey is a dependency but not an auto_install requirement of esg_csrd only from 19.0, when migrating to that version, users that don't have survey installed but do have esg will auto_install survey and pull a new computed stored field, ResUsers.karma which causes migrations issues as no script was made to account for that scenario. --- Desired behavior after this commit is merged: This commit adds survey in the auto_install requirements for the module so only instances that already have ResUsers.karma can auto_install esg_csrd --- runbot-238524 Forward-Port-Of: odoo/enterprise#113905
This fix resolves an issue where updating a manufacturing order (MO) after changing a product's design or variant could cause a system error. The change prevents users from modifying MOs based on outdated BoMs, ensuring accurate inventory management and preventing potential production disruptions. This improves stability and reliability of the manufacturing process.
Original PR description
Currently, an error occurs if a user changes the product in a BoM, updates the manufacturing order (MO) based on that BoM, and then attempts to unbuild the order. ## Steps to replicate: - Install…
Currently, an error occurs if a user changes the product in a BoM, updates the manufacturing order (MO) based on that BoM, and then attempts to unbuild the order.
## Steps to replicate:
- Install Manufacturing without demo data
- Settings > Enable Variants
- Create the following products:
- Car with (Red and Blue Color attributes)
- Red Paint
- Create a BoM for Car and product variant set to Red Car and have Red paint as the component.
- Create and Confirm manufacturing order for Red Car
- Click on Bill of Material > Set Paint required to 2 > Save
- Set product variant in BoM to Blue and save again.
- Go back to MO > Update BoM > Produce All
- Unbuild qty 1 > Confirm
## Observed Behavior:
ZeroDivisionError: float division by zero
## Root cause:
This issue occurs because the Update BoM button remains visible on the Manufacturing Order (MO) even after the product has been changed.
The problem starts when a user initially updates the required paint quantity from 1 to 2. At that point, the function [1] marks the BoM as outdated for all linked MOs, which makes the Update BoM button appear. However, if the user later changes the product template or variant, the BoM is still considered outdated. This incorrectly allows the user to update the MO using a BoM that no longer matches the selected product.
**Why this causes a traceback when unbuilding?**
When the user clicks Update BoM, it triggers the `action_update_bom function` [2], which calls `_link_bom`. This process recomputes several fields to align the MO with the updated BoM. One of the methods triggered during this recomputation is `_compute_move_finished_ids` [3]. Since the production is already confirmed, the logic skips adding the production to `production_with_move_finished_ids_to_unlink_ids`, meaning no new finished moves are created for that updated product.
As a result, although the MO is updated, its finished product (`move_finished_ids.product_id`) still refers to the original product (for example, Red Car), instead of the newly selected one.
Later, when the user attempts to unbuild the product, the `action_unbuild` function [4] is executed, which calls `_generate_consume_moves` [5] During this step, the system tries to compute a factor that depends on `unbuild.mo_id.quantity_produced`.
However, because the finished moves still reference the old product and do not match the MO’s current product, the computed total becomes zero at [6] This leads to a division by zero error at [5], which ultimately causes the traceback.
[1]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_bom.py#L432-L447 [2]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L1044-L1048 [3]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L771-L800
[4]:
https://github.com/odoo/odoo/blob/97b60952d59a57aba12b048cb4da4f41d85d2ea2/addons/mrp/models/mrp_unbuild.py#L153-L164
[5]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_unbuild.py#L225-L232 [6]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L641-L647
## Solution:
This change prevents users from updating a Bill of Materials (BoM) after the main product or its template has been modified, by ensuring the BoM is not marked as outdated.
This approach make sense because, once a manufacturing order (MO) is confirmed, all raw materials are physically reserved before production begins. While it makes sense to update BoM components in response to an Engineering Change Order (ECO) or last-minute specification changes, it does not make sense to allow changes to the final product itself on existing confirmed MOs. Doing so could lead to operational errors, since materials have already been procured and reserved for a specific product.
This fix ensures that if the product variant or product template is updated in the BoM, users cannot update the MO based on that BoM. This also prevents potential divide-by-zero errors when attempting to unbuild the product in the MO.
Reference commit which also suggests this behavior for the `Update BoM` button: [commit](https://github.com/odoo/odoo/commit/d7392829c769ef50456a7bc93d4482072b329463#:~:text=An%20exception%20however%3A%20if%20the%20MO%20is%20confirmed%20and%20the%20BoM%27s%20product%20was%0Achanged%2C%20the%20MO%20shouldn%27t%20have%20the%20%22Update%20BoM%22%20button%20displayed.%0AOtherwise%2C%20it%20would%20change%20the%20finished%20product%20of%20a%20confirmed%20MO.)
opw-6044754
Forward-Port-Of: odoo/odoo#260639
Forward-Port-Of: odoo/odoo#255981This update fixes an issue where the Mercado Pago webhook couldn't process invoices with references containing slashes (like INV/2026/00001). Previously, it resulted in a 404 error. Now, the webhook correctly handles these invoice references, ensuring accurate processing of Mercado Pago payments.
Original PR description
Currently, the mercado_pago_webhook http route only takes into consideration 1 url segment. This means that invoices with references like INV/2026/00001 don't match any defined route and the server returns a 404. /payment/mercado_pago/webhook/S00001 => OK /payment/mercado_pago/webhook/INV/2026/00001 => KO This commit allows references with slashes to be matched by the route by capturing the entire remaining url path including the slashes. /payment/mercado_pago/webhook/S00001 => OK /payment/mercado_pago/webhook/INV/2026/00001 => OK opw-6035161 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259530 Forward-Port-Of: odoo/odoo#259378
This update fixes an issue where the tip amount displayed in the Point of Sale system was incorrectly formatted (showing '415' instead of '4,15') when using a locale with a comma as the decimal separator. The fix ensures the tip amount is displayed correctly based on the user's selected language and regional settings, improving the user experience and accuracy of transactions.
Original PR description
Steps to reproduce 1. Set language decimal separator to "," and thousands separator to "." 2. Open PoS, create an order (e.g. total 17.85) 3. Pay more than the total (e.g. 22) 4. Open the Tip popup —…
Steps to reproduce
1. Set language decimal separator to "," and thousands separator to "."
2. Open PoS, create an order (e.g. total 17.85)
3. Pay more than the total (e.g. 22)
4. Open the Tip popup — it shows 415 instead of 4,15
5. Confirm — tip is set to 415
Issue
When overpaying, the change is passed as `startingValue` to the NumberPopup via
`String(amount)` (https://github.com/odoo/odoo/blob/b3d78644bc873b3b22f3fd5f8fc0cd27ce38999f/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js#L232),
which always uses "." as decimal separator. This value is used directly as the
display buffer in NumberPopup
(https://github.com/odoo/odoo/blob/b3d78644bc873b3b22f3fd5f8fc0cd27ce38999f/addons/point_of_sale/static/src/app/components/popups/number_popup/number_popup.js#L53),
so the user already sees "415" instead of "4,15" when the popup opens. When the
user confirms, `computeNewTip` parses this value with the locale-aware `parseFloat`
from `@web/views/fields/parsers`
(https://github.com/odoo/odoo/blob/b3d78644bc873b3b22f3fd5f8fc0cd27ce38999f/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js#L279
and https://github.com/odoo/odoo/blob/b3d78644bc873b3b22f3fd5f8fc0cd27ce38999f/addons/web/static/src/views/fields/parsers.js#L73-L83),
which uses `localization.thousandsSep` and `localization.decimalPoint` to interpret
the string. With "," as decimal separator and "." as thousands separator,
`parseFloat("4.15")` treats the "." as a thousands separator, strips it, and
returns 415 instead of 4.15.
opw-5895622
Forward-Port-Of: odoo/odoo#255273This update fixes an issue where employees were incorrectly paid 80% for rest days when on sick leave. The change ensures that employees are paid their full wage on rest days, aligning with the definition of a sickness day. This corrects a miscalculation impacting payroll accuracy.
Original PR description
Currently, if a sick leave is spread over a weekend, the work entry type set on the saturday and sunday will be the sick leave type. If an employee is entitled sickness allowance (which is paid 80%), it means that we will be paying them 80% for their rest days as well. However, as per the definition, a sickness day is a day on which an employee is absent from work by reason of being unfit due to injury or sickness. If an employee is not expected to be at work (rest day), that day cannot be considered a sickness day. If this rest day is paid (which is done by default in our module), we should thus pay the full wage on that day and not a reduced 80%. task-6079736 Forward-Port-Of: odoo/enterprise#114841 Forward-Port-Of: odoo/enterprise#113486
This update fixes an issue where the forecast report incorrectly grouped purchase orders with different receipt dates for the same product. The fix ensures that each unique receipt date is accurately represented in the forecast details, providing a more precise view of inventory availability. This improves the reliability of inventory planning.
Original PR description
If you make a purchase order with 2 quantity of the same product, and set 2 different receipt date. The forecast report details would incorrectly group them as the same line. Steps to reproduce: ------------------- * Create a purchase order * Add 2 lines with the same product * Change the receipt date for one of the 2 lines * Go to the forecast report of the product > Observation: In the forecast details there is only one line for the first receipt date. Why the fix: ------------ We add a condition in the `_sameDocument` function to check that the 2 documents being compared have the same receipt date opw-5361583 Forward-Port-Of: odoo/odoo#254170
This update fixes an issue where approving overtime on one attendance record would reset previously approved overtime for the same week. The change ensures that approved overtime remains approved, streamlining the attendance management process and preventing unnecessary re-approvals. It corrects a logic error in how the system updates attendance records.
Original PR description
Creating or updating an attendance record resets previously approved overtime entries in the same week back to the 'to_approve' status. ### **Steps to reproduce:** 1) Install Attendance with demo…
Creating or updating an attendance record resets previously approved overtime entries in the same week back to the 'to_approve' status. ### **Steps to reproduce:** 1) Install Attendance with demo data. 2) Set 'Extra Hours Validation' to 'Approved by Manager' in settings. 3) Ensure an overtime rule is set for the Admin user. 4) Create an attendance for Admin with some overtime. 5) Navigate to management and approve overtime. 6) Create another attendance with overtime for Admin in the same week. 7) Navigate back to management. ### **Observed Behavior:** Previously approved overtime reappears in the list, requiring approval again. ### **Expected Behavior:** Previous overtime should remain in the 'approved' status, provided its calculated duration has not changed. ### **Root Cause:** When an attendance is added or modified, the [_get_overtimes_to_update_domain](https://github.com/odoo/odoo/blob/3891dd471d64629634644c0b022a171bbaa65b49/addons/hr_attendance/models/hr_attendance.py#L268-L286) method evaluates the entire week regardless of the ruleset. This means any daily attendance update wipes and recreates the entire week. ### **Fix:** Check the ruleset of the employee. If no rule has `quantity_period` set to **'week'**, restrict the domain to the specific days of the attendances being modified, rather than the entire week. **opw-6054497** Forward-Port-Of: odoo/odoo#259872 Forward-Port-Of: odoo/odoo#256281
This update ensures the VIES summary report XML files generated for Czech companies correctly format VAT numbers. Previously, the report included the country code, which is now removed to comply with official VIES XML requirements. This ensures accurate reporting and avoids potential issues with tax authorities.
Original PR description
**Steps to reproduce:** - Install the `l10n_cz_reports` module and switch to a `CZ Company` - Create an invoice for a customer with a VAT number, add a product, and set the Transaction Code (enable…
**Steps to reproduce:** - Install the `l10n_cz_reports` module and switch to a `CZ Company` - Create an invoice for a customer with a VAT number, add a product, and set the Transaction Code (enable it from the optional columns if needed). - Navigate to Reporting > VIES Summary Report. - Observe the value in the `VAT Number` column (includes country code). - From the dropdown, export the report as XML. **Observation:** In the generated XML file, the `c_vat` field contains the VAT number including the country code (e.g., `CZ12345679`) instead of only the numeric part (`12345679`). **Root cause:** At [1], the VAT number is directly taken from the report lines without removing the country code. **Fix:** This commit ensures that the `c_vat` field contains only the VAT number without the country code, complying with the official VIES XML format requirements. Ref: https://adisspr.mfcr.cz/dpr/adis/idpr_pub/epo2_info/popis_struktury_detail.faces?zkratka=DPHSHV#:~:text=Tax%20identification%20number%20of%20the%20purchaser%20(only%20the%20numeric%20part) [1]: https://github.com/odoo/enterprise/blob/c4f2c3442f30f5ac972dd136a3642acc5bcc6da2/l10n_cz_reports_2025/models/l10n_cz_vies_summary_handler.py#L29-L62 opw-6093259 Forward-Port-Of: odoo/enterprise#114730 Forward-Port-Of: odoo/enterprise#113083
This update resolves an issue where the original product name was incorrectly prepended to product descriptions on invoices and RFQs when editing. The fix ensures that only translated names and descriptions are displayed, improving invoice clarity and accuracy for users. This change impacts invoicing and purchasing workflows.
Original PR description
Steps to reproduce: 1- Install invoicing app 2- Add French language in the settings 3- Create a customer with language set as French 4- Create a product and define french translations of the name and…
Steps to reproduce: 1- Install invoicing app 2- Add French language in the settings 3- Create a customer with language set as French 4- Create a product and define french translations of the name and the description in Sales tab 5- Create an invoice for that customer and choose the product you created 6- You will find the translated product name and description under the product name 7- Edit the description, save and preview the invoice 8- The invoice line will contain [Product Name EN] [Product Name FR] [Product Description FR] Description of the issue: When creating an invoice for a customer whose language differs from the user's account language, manually editing the product description on an invoice line causes the original product name to be prepended to the description. The same issue happens in a RFQ in Purchase. Expected behaviour: User can edit the product description in the invoice line and the output in the invoice should only be the translated name and description, without the original product name. Why this happens? 1- When the product is selected in the invoice line, the label is loaded from _compute_name method in account_move_line, which holds the translated name and description. 2- After editing the description and escaping the field (clicking outside it), the parseLabel method is called, which prepends the original name to the label, making the invoice output as [original name] [translated name] [translated desc.] Fix: Use the product name returned in the label for trimming and concatenation to handle both original/translated text scenarios. References: original PR: #248401 partial revert: #254158 opw-5480494 Forward-Port-Of: odoo/odoo#256837
This update fixes an issue where draft stock moves were incorrectly flagged as unavailable, even when sufficient stock existed. The change adjusts how availability is calculated to accurately reflect available stock, ensuring accurate forecasts and preventing fulfillment delays. This improves the reliability of stock management.
Original PR description
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is…
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is displayed in red (not available), even though the stock is sufficient to fulfill the move. Explication: For draft consuming moves, the forecast availability is computed as: `virtual_available - move.product_qty` In the case where stock exactly matches the demand, this results in 0. However, on the JS side, availability is evaluated with: `forecast_availability >= product_qty` So with forecast_availability = 0 and product_qty = 2, the condition evaluates to False, incorrectly marking the move as not available. https://github.com/odoo/odoo/blob/c7fede7f44c668ccc0a094d8341c3cae8879a7f1/addons/stock/static/src/widgets/forecast_widget.js#L31 Solution: When the available quantity is sufficient to cover the move (using float_compare), set forecast_availability to the full available quantity instead of subtracting the move quantity. This ensures the JS condition correctly evaluates to True and the move is marked as available. opw-5159142 Forward-Port-Of: odoo/odoo#258504 Forward-Port-Of: odoo/odoo#257354
This update resolves an issue where role mentions weren't working correctly within the full composer, leading to emails being sent to incorrect addresses or failing to send at all. The fix ensures role mentions are displayed accurately and links function properly, improving the reliability of email communication within Odoo. This ensures users can effectively tag roles in emails.
Original PR description
There is an issue when tagging a role using the full composer: 1. Emails are sent to the wrong address or sometimes no address at all 2. The displayed URL is not correct This commit fixes the issue by correctly rendering the mention block for roles in the full composer, using the correct configuration. task-6139162 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260457 Forward-Port-Of: odoo/odoo#260094
This update enhances the account reports feature on mobile devices by ensuring the chatter is always visible and the annotation icon is consistently accessible via touch. This improves usability for users accessing reports on phones and tablets, making it easier to review and annotate information.
Original PR description
Previously, the chatter was hidden on device too smalls and the annotation icon was only visible with hover so not visible on touch devices such as phones or tablets. Now, we have the chatter at the bottom when the device is too small and always display the annotation icon on touch devices. task-5106852 Forward-Port-Of: odoo/enterprise#114700 Forward-Port-Of: odoo/enterprise#95737
This update corrects a previous issue where payroll calculations were inaccurate for employees with contracts that didn't fully overlap with the payslip period. Now, the system correctly identifies and handles fully out-of-contract payslips, preventing incorrect calculations and ensuring accurate reporting. Partially overlapping payslips continue to compute as expected.
Original PR description
Fix:- Block payslip computation when the payslip period does not overlap the employee's contract period. Before this change:- Employees with contracts starting and ending before the payslip period will have 'worked days' and computation will yield numbers even though this is not accurate. After this change: - compute raises "No running contract" for fully out-of-contract slips, - worked days summary stays at 0, -`Out Of Contract` worked day lines are preserved, - partially overlapping payslips still compute as expected. task-[6055170](https://www.odoo.com/odoo/project/1251/tasks/6055170)
This update fixes a confusing error message that appeared when employees changed their contracts and working schedules, particularly when leaves were involved. The fix now includes the original error traceback, making it easier for administrators to understand and resolve the issue related to leave allocations.
Original PR description
A validation error is raised if changing employee's contract with a new working schedule on a period with leaves and the new working schedule changes the duration of these leaves in such a way that the employee no longer has the required allocation for them. This adds to the error message the original error traceback for debuggig purposes. Task: 6105516 Forward-Port-Of: odoo/odoo#258280
This update fixes an issue where increasing the quantity of a service product in a sales order incorrectly generated a purchase order with an inflated quantity. The fix ensures the quantity is always calculated and expressed in the sales order's unit of measure, resolving a discrepancy in the purchase order generation process. This prevents over-ordering and ensures accurate purchase order quantities.
Original PR description
Steps to reproduce the bug: - Create a service product "P1": - In the Purchase tab: - Vendor: Azure Interior - Subcontract Service: True - UoM: dozen - Purchase UoM: unit - Create a sales order with…
Steps to reproduce the bug:
- Create a service product "P1":
- In the Purchase tab:
- Vendor: Azure Interior
- Subcontract Service: True
- UoM: dozen
- Purchase UoM: unit
- Create a sales order with 1 dozen of P1
- Confirm -> a purchase order with 12 units of P1 is generated
- Confirm the purchase order
- Go back to the sales order:
- Update the quantity from 1 to 2 dozen
Problem:
A new purchase order is generated, but with 144 units instead of 12
units. The quantity difference between the old SO quantity and the new
one is computed twice in the purchase order line UoM, in both
`_purchase_increase_ordered_qty` and `_purchase_service_prepare_line_values`:
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L186
Solution:
The `quantity` parameter must be expressed in the SO line UoM, as
described in the documentation of the function `_purchase_service_prepare_line_values`.
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L178
opw-6049106
Forward-Port-Of: odoo/odoo#260517
Forward-Port-Of: odoo/odoo#255478This update fixes an issue where MTSO procurements were incorrectly estimating available stock due to how free quantities were calculated. The change ensures that stock availability is accurately reflected across multiple levels of a product's bill of materials, preventing over-ordering of components. This improves procurement accuracy and reduces potential stock discrepancies.
Original PR description
When creating a procurement through mtso, if the product has a muti level bom with the same component at multiple levels, it will consider the available quantity multiple times. Steps to reproduce:…
When creating a procurement through mtso, if the product has a muti level bom with the same component at multiple levels, it will consider the available quantity multiple times. Steps to reproduce: ------------------- * Enable MTO and change supply method to: "Take From Stock, if unavailable, Trigger Another Rule" * Create three products : final, semi, component - final: mtso, manufacture - semi: mtso, manufacture - component: mtso, buy, on hand quantity to 4 * Create a bom for final: - 10 components - 1 semi * Create a bom for semi: - 10 components * Create and confirm a MO for 1 "final" -> Issue the purchase order is only for 12 components and not 16. Observation: ------------- When confirming our MO, it will create a manufacture procurement for the products. The procurement will recursively create procurements and stock moves for each of its components. https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1563-L1571 Since its a MTSO, it will first check the products if there is available products in stock (free_qty) and create the procurement for the missing quantity: https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1646-L1647 https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1657-L1663 And each procurement, if it is of the manufacture type, will create corresponding procurements for their components. Once all the procurements and stock moves have been created, the stock move will confirmed and assigned. https://github.com/odoo/odoo/blob/942cbbbf243ff28f84fdaa40ed73b6572e0032a6/addons/stock/models/stock_move.py#L1627-L1629 -> The issue arise because the free_qty will only be updated when the stock moves are assigned which happen after all the procurement quantity are calculated for all the levels. opw-5514788 Forward-Port-Of: odoo/odoo#253958
This update ensures that Brazilian fiscal documents generated for EDI comply with local tax regulations. The system now incorporates approximate tax values provided by Avalara, which are legally required to be included in all documents, even when no specific tax information is available. This improves accuracy and avoids potential compliance issues.
Original PR description
All fiscal documents are required by Brazil law to include the approximate value of fed, state, and city taxes that affect it. Avalara already provides back these values in their tax calculation response, we just missed sending it to the EDI. This commit takes the information from that response and adds it to the EDI payload to make sure that it is generated properly into the generated documents. We are required to always show this even if there are no informative taxes as such we combine it with the T&C sent already. task-5478059 Forward-Port-Of: odoo/enterprise#113732
This update resolves an issue where downloading attachments from Odoo's mobile apps was failing. The fix ensures that absolute URLs for attachments are correctly handled, preventing errors and restoring the ability to download files from the chatter interface. This improves the user experience for mobile users.
Original PR description
In Odoo 18.4+, downloading attachments from the chatter is broken.
See: https://github.com/odoo/odoo/pull/200099
The `onClickDownload` function now passes an absolute URL to `downloadFile`.
The download function is implemented natively in the mobile apps.
The Android implementation always prefixes the provided URL with the
database origin (i.e.: `https://example.odoo.com`).
`download({url: "https://example.odoo.com/web/content"})` will try to
download `https://example.odoo.comhttps://example.odoo.com/web/content`.
This results in an UnknownHostException.
We can remove the origin from the url before calling the native method.
By doing this on the JS side, there is no need to update the Android app.
opw-6033150
Forward-Port-Of: odoo/enterprise#114832