Daily updates from Odoo
Wednesday, July 15, 2026
332 changes
14 changes
Enhancements to existing features
Improve (mass_)mailing asserts and tools, notably to use their usage in marketing automation where simulating user actions (open emails, reply, ...) is necessary to check marketing activities scheduling and execution. Task-4224152: [marketing_automation] Performance / Scalability Forward-Port-Of: odoo/odoo#276198 Forward-Port-Of: odoo/odoo#275964
Original PR description
Improve (mass_)mailing asserts and tools, notably to use their usage in marketing automation where simulating user actions (open emails, reply, ...) is necessary to check marketing activities scheduling and execution. Task-4224152: [marketing_automation] Performance / Scalability Forward-Port-Of: odoo/odoo#276198 Forward-Port-Of: odoo/odoo#275964
Resolved issues and error corrections
### Steps to reproduce 1. Create a invoice with a section and add products under it with values 2. Enable **Hide Composition** on the section. 3. Print the invoice PDF. <table> <tr> <td> <img width="1278" height="425" alt="image" src="https://github.com/user-attachments/assets/969a222a-5e2f-48e2-962d-fc1cf6440619" /> </td> </tr> </table> ### Description When an invoice contains a section and products in it with values and with **Hide Composition** enabled,
Original PR description
### Steps to reproduce 1. Create a invoice with a section and add products under it with values 2. Enable **Hide Composition** on the section. 3. Print the invoice PDF. <table> <tr> <td> <img…
### Steps to reproduce
1. Create a invoice with a section and add products under it with values
2. Enable **Hide Composition** on the section.
3. Print the invoice PDF.
<table>
<tr>
<td>
<img width="1278" height="425" alt="image" src="https://github.com/user-attachments/assets/969a222a-5e2f-48e2-962d-fc1cf6440619" />
</td>
</tr>
</table>
### Description
When an invoice contains a section and products in it with values and with **Hide Composition** enabled, the PDF invoice report incorrectly displays the **Disc.%** column header even though no discount values in that section line.
The report currently computes `display_discount` using `o.invoice_line_ids`:
```xml
<t t-set="display_discount" t-value="any(l.discount for l in o.invoice_line_ids)"/>
```
Since `o.invoice_line_ids` still contains the hidden product lines, `display_discount` evaluates to `True`, causing the **Disc.%** column header to be displayed. However, those product lines are replaced by the section line in the report, so no discount values are shown, resulting in an empty column.
### Current behavior
The **Disc.%** column is displayed, but all its cells are empty.
<table>
<tr>
<td>
<img width="808" height="488" alt="image" src="https://github.com/user-attachments/assets/7d9afee6-fef5-49c8-bc4e-b01caa8b43bd" />
</td>
</tr>
</table>
### Expected behavior
The **Disc.%** column should not be displayed when the reported lines do not contain any discounts.
<table>
<tr>
<td>
<img width="798" height="427" alt="image" src="https://github.com/user-attachments/assets/6ffe7985-a7d0-43f5-8d40-41e700ecbed3" />
</td>
</tr>
</table>
### Solution
Compute `lines_to_report` before evaluating `display_discount` and use it instead:
```xml
<t t-set="lines_to_report" t-value="o._get_move_lines_to_report()"/>
<t t-set="display_discount" t-value="any(l.discount for l in lines_to_report)"/>
```
Forward-Port-Of: odoo/odoo#276003
Forward-Port-Of: odoo/odoo#275793Only display the AI thread start message once the thread has finished loading, matching the behavior of regular Discuss channels and preventing a brief flash of the empty conversation. Update the AI-specific `showStartMessage` implementation to respect the base Thread loading state instead of always displaying the start message for AI channels. Enterprise PR : https://github.com/odoo/enterprise/pull/122808 task-6352578 --- I confirm I have signed the CLA and read the PR guidelines a
Original PR description
Only display the AI thread start message once the thread has finished loading, matching the behavior of regular Discuss channels and preventing a brief flash of the empty conversation. Update the AI-specific `showStartMessage` implementation to respect the base Thread loading state instead of always displaying the start message for AI channels. Enterprise PR : https://github.com/odoo/enterprise/pull/122808 task-6352578 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273991
Steps to reproduce: Have one invoice Posted, To Review Have one invoice Draft, To Review Dashboard will only says 1 To Review When clicking the link it shows 2 invoices After this commit- We append the domain of the filter with only posted moves task-6385625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276261
Original PR description
Steps to reproduce: Have one invoice Posted, To Review Have one invoice Draft, To Review Dashboard will only says 1 To Review When clicking the link it shows 2 invoices After this commit- We append the domain of the filter with only posted moves task-6385625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276261
Steps to Reproduce: - open notes - type `/link` to open link popover Issue: - The url input field and its icon are misaligned. Cause: - When url autocomplete are enabled in the link popover, the input field height is reduced, causing it to become smaller than its container. This results in misalignment between the input field and the icon. Solution: - Set the link popover url input height to 100% so it always matches the height of its container, ensuring proper alignment even when
Original PR description
Steps to Reproduce: - open notes - type `/link` to open link popover Issue: - The url input field and its icon are misaligned. Cause: - When url autocomplete are enabled in the link popover, the input field height is reduced, causing it to become smaller than its container. This results in misalignment between the input field and the icon. Solution: - Set the link popover url input height to 100% so it always matches the height of its container, ensuring proper alignment even when autocomplete is avaialble. task-6201175 Forward-Port-Of: odoo/odoo#267716
Chrome keeps suggesting autocompletion on empty selection field. https://github.com/odoo/odoo/commit/5e7bc4ab851dba3d2e0b965f69e06cfeacec5674 is the commit introducing `autocomplete="selectMenuAutocompleteOff"` and I don't know why this value has been chosen but Chrome seem to consider this token as invalid Steps to reproduce: - Put a selection field on a form view with Studio - Create a record, complete the selection field and save - Create a new record and click on the selection field
Original PR description
Chrome keeps suggesting autocompletion on empty selection field. https://github.com/odoo/odoo/commit/5e7bc4ab851dba3d2e0b965f69e06cfeacec5674 is the commit introducing `autocomplete="selectMenuAutocompleteOff"` and I don't know why this value has been chosen but Chrome seem to consider this token as invalid Steps to reproduce: - Put a selection field on a form view with Studio - Create a record, complete the selection field and save - Create a new record and click on the selection field Current Behaviour: Chrome keeps suggesting the previously filled values Desired Behaviour: No autocomplete from the browser. Forward-Port-Of: odoo/odoo#276142 Forward-Port-Of: odoo/odoo#274086
Steps to reproduce: - Add an `s_add_to_cart` snippet inside a mega menu - Open a product detail page for a storable product - Change the product variant several times - Stock availability messages keep appending under `availability_messages` instead of replacing the previous one `_onChangeCombinationStock` removed existing messages with `document.querySelector('.oe_website_sale').querySelectorAll(...)`, but appended the new message with `this.el.querySelector('div.availability_messages')
Original PR description
Steps to reproduce: - Add an `s_add_to_cart` snippet inside a mega menu - Open a product detail page for a storable product - Change the product variant several times - Stock availability messages…
Steps to reproduce:
- Add an `s_add_to_cart` snippet inside a mega menu
- Open a product detail page for a storable product
- Change the product variant several times
- Stock availability messages keep appending under `availability_messages` instead of replacing the previous one
`_onChangeCombinationStock` removed existing messages with `document.querySelector('.oe_website_sale').querySelectorAll(...)`, but appended the new message with
`this.el.querySelector('div.availability_messages').append(...)`.
`document.querySelector('.oe_website_sale')` only returns the first `.oe_website_sale` element in the document. When a mega menu contains an `s_add_to_cart` snippet, that element appears before the product page container, so the removal step runs on the wrong subtree and never clears the messages on the product page.
Fix by scoping the removal to `this.el`, the current `WebsiteSale` interaction root, so both removal and insertion target the same product page container.
Forward-Port-Of: odoo/odoo#276252
Forward-Port-Of: odoo/odoo#274928Previously, batch payment sequence will be created by simply select to create new company due to having lambda in default. Hence, the created sequence does not have a correct company_id set as company hasn't yet created. Switch to creating sequence in ``create`` function to avoid this issue. Also use ``range_year`` for payment prefix because it was set to use date range. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged:
Original PR description
Previously, batch payment sequence will be created by simply select to create new company due to having lambda in default. Hence, the created sequence does not have a correct company_id set as company hasn't yet created. Switch to creating sequence in ``create`` function to avoid this issue. Also use ``range_year`` for payment prefix because it was set to use date range. 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#276182 Forward-Port-Of: odoo/odoo#268689
When a POS line comes from a sale order, its invoice line name is overridden with the source sale order line's name. When a down payment is invoiced directly from the POS, the invoice is generated before the down payment POS line is linked to its sale order line, so sale_order_line_id is still empty and the override resolved to an empty recordset, setting the invoice line name to False. Only override the name when a sale order line is actually set, so the down payment line keeps its own name.
Original PR description
When a POS line comes from a sale order, its invoice line name is overridden with the source sale order line's name. When a down payment is invoiced directly from the POS, the invoice is generated before the down payment POS line is linked to its sale order line, so sale_order_line_id is still empty and the override resolved to an empty recordset, setting the invoice line name to False. Only override the name when a sale order line is actually set, so the down payment line keeps its own name. opw-6305649 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275516 Forward-Port-Of: odoo/odoo#274000
Currently, when using the "login with employee" feature and sending the order receipt by mail, the cashier name is not the name of the employee using the pos. Steps to reproduce: ------------------- * Use the login with employee feature * Open the pos * Connect with an employee not linked to the current user * Make an order * Send the receipt to the customer by mail. > The receipt from the shop shows the cashier's name, the receipt sent by mail shows the connected user as the cashier
Original PR description
Currently, when using the "login with employee" feature and sending the order receipt by mail, the cashier name is not the name of the employee using the pos. Steps to reproduce: ------------------- * Use the login with employee feature * Open the pos * Connect with an employee not linked to the current user * Make an order * Send the receipt to the customer by mail. > The receipt from the shop shows the cashier's name, the receipt sent by mail shows the connected user as the cashier opw-6291485 Forward-Port-Of: odoo/odoo#270013
### Before this PR When importing a FatturaPA XML, Odoo sets the fiscal position on the bill from the partner but does not apply it to the line taxes so a fiscal position that remaps taxes (partial deductibility, reverse charge, split payment) never map the imported lines. ### After this PR the fiscal position is correctly applied ### To reproduce 1. Apply to Italian vendor a fiscal position that maps the 22% purchase tax to a partial-deductibility tax (e.g. "22%" →"22% ind. 50%").
Original PR description
### Before this PR When importing a FatturaPA XML, Odoo sets the fiscal position on the bill from the partner but does not apply it to the line taxes so a fiscal position that remaps taxes (partial deductibility, reverse charge, split payment) never map the imported lines. ### After this PR the fiscal position is correctly applied ### To reproduce 1. Apply to Italian vendor a fiscal position that maps the 22% purchase tax to a partial-deductibility tax (e.g. "22%" →"22% ind. 50%"). 2. Import a FatturaPA XML from that vendor with 22% lines. 3. The bill header shows the fiscal position, but the lines keep the plain 22% tax instead of the mapped one. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275614 Forward-Port-Of: odoo/odoo#274738
**PROBLEM** amount_to_invoice_at_date is not calculated correctly when using UoM. **STEP TO REPRODUCE** 1. Create a product tracked by unit. 2. Create a purchase order with a UoM of pack of 6 (or some multiples of the Units UoM). 3. Confirm the PO and receive the products. 4. Go to the accounting app, reviews>bill to receive 5. Notice the po line on bill to receive as an incorrect amount. opw-6305324 Forward-Port-Of: odoo/odoo#275876 Forward-Port-Of: odoo/odoo#270327
Original PR description
**PROBLEM** amount_to_invoice_at_date is not calculated correctly when using UoM. **STEP TO REPRODUCE** 1. Create a product tracked by unit. 2. Create a purchase order with a UoM of pack of 6 (or some multiples of the Units UoM). 3. Confirm the PO and receive the products. 4. Go to the accounting app, reviews>bill to receive 5. Notice the po line on bill to receive as an incorrect amount. opw-6305324 Forward-Port-Of: odoo/odoo#275876 Forward-Port-Of: odoo/odoo#270327
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a barcode for the product with the B variant only - Go to the PoS, enter the barcode for the product with the B variant - The price is 1400 instead of 1200 **Why the fix:** The extra price for dynamic variants ordered through the barcode will be counted twice. This is because it is first count
Original PR description
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a…
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a barcode for the product with the B variant only - Go to the PoS, enter the barcode for the product with the B variant - The price is 1400 instead of 1200 **Why the fix:** The extra price for dynamic variants ordered through the barcode will be counted twice. This is because it is first counted in the _scan(code) method when we fetch the product from the models, then counted again when adding the line to the current order. https://github.com/odoo/odoo/blob/f4d079cc5a9c47672cf1a6747bb073e8e74f7350/addons/point_of_sale/static/src/app/services/pos_store.js#L1264-L1269 This step is necessary for the usual flow without the barcode as we need to add this extra price, but when using the barcode, the list price of the product we fetch is already 1200, as the extra price is already included when fetching it from the backend. It works for always attributes because we explicitly check that we are not adding the extra price again in the above code, and that the list price already includes the extra price. It also works for the never attributes because values.product_id.product_template_variant_value_ids.length is 0, so the code to update the extra price is never triggered. As we still need to add the extra price for the usual flow, we now just check if we have a code, meaning we added the product through the barcode and that we do not need to add it again, as the list price already accounts for the extra price. opw-6328600 Forward-Port-Of: odoo/odoo#272395
In main data service of this PoS indexedDB is called automatically after records are updated. ```js this.debouncedSynchronizeLocalDataInIndexedDB = debounce( this.synchronizeLocalDataInIndexedDB.bind(this), 300 ); ``` But sometimes, the indexedDB is directly called in the code via `synchronizeLocalDataInIndexedDB` which is not debounced and can lead to race conditions and potential data corruption. Now the `synchronizeLocalDataInIndexedDB` is inside a Mutex to avoid concurr
Original PR description
In main data service of this PoS indexedDB is called automatically after records are updated.
```js
this.debouncedSynchronizeLocalDataInIndexedDB = debounce(
this.synchronizeLocalDataInIndexedDB.bind(this),
300
);
```
But sometimes, the indexedDB is directly called in the code via `synchronizeLocalDataInIndexedDB` which is not debounced and can lead to race conditions and potential data corruption.
Now the `synchronizeLocalDataInIndexedDB` is inside a Mutex to avoid concurrent access to the indexedDB.
The old method is renamed to `_synchronizeLocalDataInIndexedDB` and is now private.
Forward-Port-Of: odoo/odoo#27589211 changes
Resolved issues and error corrections
### Steps to reproduce 1. Create a invoice with a section and add products under it with values 2. Enable **Hide Composition** on the section. 3. Print the invoice PDF. <table> <tr> <td> <img width="1278" height="425" alt="image" src="https://github.com/user-attachments/assets/969a222a-5e2f-48e2-962d-fc1cf6440619" /> </td> </tr> </table> ### Description When an invoice contains a section and products in it with values and with **Hide Composition** enabled,
Original PR description
### Steps to reproduce 1. Create a invoice with a section and add products under it with values 2. Enable **Hide Composition** on the section. 3. Print the invoice PDF. <table> <tr> <td> <img…
### Steps to reproduce
1. Create a invoice with a section and add products under it with values
2. Enable **Hide Composition** on the section.
3. Print the invoice PDF.
<table>
<tr>
<td>
<img width="1278" height="425" alt="image" src="https://github.com/user-attachments/assets/969a222a-5e2f-48e2-962d-fc1cf6440619" />
</td>
</tr>
</table>
### Description
When an invoice contains a section and products in it with values and with **Hide Composition** enabled, the PDF invoice report incorrectly displays the **Disc.%** column header even though no discount values in that section line.
The report currently computes `display_discount` using `o.invoice_line_ids`:
```xml
<t t-set="display_discount" t-value="any(l.discount for l in o.invoice_line_ids)"/>
```
Since `o.invoice_line_ids` still contains the hidden product lines, `display_discount` evaluates to `True`, causing the **Disc.%** column header to be displayed. However, those product lines are replaced by the section line in the report, so no discount values are shown, resulting in an empty column.
### Current behavior
The **Disc.%** column is displayed, but all its cells are empty.
<table>
<tr>
<td>
<img width="808" height="488" alt="image" src="https://github.com/user-attachments/assets/7d9afee6-fef5-49c8-bc4e-b01caa8b43bd" />
</td>
</tr>
</table>
### Expected behavior
The **Disc.%** column should not be displayed when the reported lines do not contain any discounts.
<table>
<tr>
<td>
<img width="798" height="427" alt="image" src="https://github.com/user-attachments/assets/6ffe7985-a7d0-43f5-8d40-41e700ecbed3" />
</td>
</tr>
</table>
### Solution
Compute `lines_to_report` before evaluating `display_discount` and use it instead:
```xml
<t t-set="lines_to_report" t-value="o._get_move_lines_to_report()"/>
<t t-set="display_discount" t-value="any(l.discount for l in lines_to_report)"/>
```
Forward-Port-Of: odoo/odoo#276003
Forward-Port-Of: odoo/odoo#275793The reporting labels "Difference" and "Balance" are confusing because "Difference" tracks system-qualified overtime while "Balance" represents accepted overtime hours. There is also a lack of consistency across views. This commit renames these fields to "Worked Extra Hours" and "Validated Extra Hours" to harmonize the naming everywhere task-6352142 Description of the issue/feature this PR addresses: Confusing and inconsistent naming for extra hours Current behavior before PR: - Rep
Original PR description
The reporting labels "Difference" and "Balance" are confusing because "Difference" tracks system-qualified overtime while "Balance" represents accepted overtime hours. There is also a lack of consistency across views. This commit renames these fields to "Worked Extra Hours" and "Validated Extra Hours" to harmonize the naming everywhere task-6352142 Description of the issue/feature this PR addresses: Confusing and inconsistent naming for extra hours Current behavior before PR: - Reporting uses "Difference" and "Balance". - Views use inconsistent labels. Desired behavior after PR is merged: Labels are consistently named "Worked Extra Hours" and "Validated Extra Hours" everywhere. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275944 Forward-Port-Of: odoo/odoo#273631
Steps to reproduce: Have one invoice Posted, To Review Have one invoice Draft, To Review Dashboard will only says 1 To Review When clicking the link it shows 2 invoices After this commit- We append the domain of the filter with only posted moves task-6385625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276261
Original PR description
Steps to reproduce: Have one invoice Posted, To Review Have one invoice Draft, To Review Dashboard will only says 1 To Review When clicking the link it shows 2 invoices After this commit- We append the domain of the filter with only posted moves task-6385625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276261
### [FIX] portal: fix parent company handling Before this commit, users could not update the company name from the portal, and creating a company resulted in a regular contact instead of a company. This happened because the additional_values passed to mark the parent as is_company=True were overridden to False when the customer did not have a VAT number. This commit sets is_company after creating the company, ensuring the parent contact is always created as a company. ### [FIX] portal:
Original PR description
### [FIX] portal: fix parent company handling Before this commit, users could not update the company name from the portal, and creating a company resulted in a regular contact instead of a company. This happened because the additional_values passed to mark the parent as is_company=True were overridden to False when the customer did not have a VAT number. This commit sets is_company after creating the company, ensuring the parent contact is always created as a company. ### [FIX] portal: make commercial fields editable Before this commit, there was no way to edit commercial fields after a user entered a company name in the address form. Setting a company name created a parent company, and editing commercial fields was blocked because the customer had a parent record. This commit allows commercial fields to be edited again for customer addresses whose parent company has only a single direct child. Forward-Port-Of: odoo/odoo#276015 Forward-Port-Of: odoo/odoo#275207
This fix is the same as this one https://github.com/odoo/odoo/pull/271577 but for the backend part of the code. After the fix, if you followed the same steps to reproduce and tried to close the session you would have an unbalanced entry for the session. Steps to reproduce: ------------------- * Create a 21% tax not included in price * Create a product with a price of 76.01 and the tax created above * Create a loyalty program with a 10% discount * Create a POS order with the product ab
Original PR description
This fix is the same as this one https://github.com/odoo/odoo/pull/271577 but for the backend part of the code. After the fix, if you followed the same steps to reproduce and tried to close the session you would have an unbalanced entry for the session. Steps to reproduce: ------------------- * Create a 21% tax not included in price * Create a product with a price of 76.01 and the tax created above * Create a loyalty program with a 10% discount * Create a POS order with the product above and apply the loyalty program * Validate the order and generate the invoice * Close the session > Observation: You need to force close the session because of unbalanced entry Why the fix: ------------ Apply the same fix for backend code. opw-6052112 Forward-Port-Of: odoo/odoo#276100 Forward-Port-Of: odoo/odoo#274985
Backport the changes from `b9370ea6b70ca3020c73a6940d70ff0cf954f69f` into `mail/convert_inline` to ensure Outlook-compatible image rendering. opw-3776054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276071 Forward-Port-Of: odoo/odoo#269436
Original PR description
Backport the changes from `b9370ea6b70ca3020c73a6940d70ff0cf954f69f` into `mail/convert_inline` to ensure Outlook-compatible image rendering. opw-3776054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276071 Forward-Port-Of: odoo/odoo#269436
Currently, when using the "login with employee" feature and sending the order receipt by mail, the cashier name is not the name of the employee using the pos. Steps to reproduce: ------------------- * Use the login with employee feature * Open the pos * Connect with an employee not linked to the current user * Make an order * Send the receipt to the customer by mail. > The receipt from the shop shows the cashier's name, the receipt sent by mail shows the connected user as the cashier
Original PR description
Currently, when using the "login with employee" feature and sending the order receipt by mail, the cashier name is not the name of the employee using the pos. Steps to reproduce: ------------------- * Use the login with employee feature * Open the pos * Connect with an employee not linked to the current user * Make an order * Send the receipt to the customer by mail. > The receipt from the shop shows the cashier's name, the receipt sent by mail shows the connected user as the cashier opw-6291485 Forward-Port-Of: odoo/odoo#270013
### Before this PR When importing a FatturaPA XML, Odoo sets the fiscal position on the bill from the partner but does not apply it to the line taxes so a fiscal position that remaps taxes (partial deductibility, reverse charge, split payment) never map the imported lines. ### After this PR the fiscal position is correctly applied ### To reproduce 1. Apply to Italian vendor a fiscal position that maps the 22% purchase tax to a partial-deductibility tax (e.g. "22%" →"22% ind. 50%").
Original PR description
### Before this PR When importing a FatturaPA XML, Odoo sets the fiscal position on the bill from the partner but does not apply it to the line taxes so a fiscal position that remaps taxes (partial deductibility, reverse charge, split payment) never map the imported lines. ### After this PR the fiscal position is correctly applied ### To reproduce 1. Apply to Italian vendor a fiscal position that maps the 22% purchase tax to a partial-deductibility tax (e.g. "22%" →"22% ind. 50%"). 2. Import a FatturaPA XML from that vendor with 22% lines. 3. The bill header shows the fiscal position, but the lines keep the plain 22% tax instead of the mapped one. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275614 Forward-Port-Of: odoo/odoo#274738
**PROBLEM** amount_to_invoice_at_date is not calculated correctly when using UoM. **STEP TO REPRODUCE** 1. Create a product tracked by unit. 2. Create a purchase order with a UoM of pack of 6 (or some multiples of the Units UoM). 3. Confirm the PO and receive the products. 4. Go to the accounting app, reviews>bill to receive 5. Notice the po line on bill to receive as an incorrect amount. opw-6305324 Forward-Port-Of: odoo/odoo#275876 Forward-Port-Of: odoo/odoo#270327
Original PR description
**PROBLEM** amount_to_invoice_at_date is not calculated correctly when using UoM. **STEP TO REPRODUCE** 1. Create a product tracked by unit. 2. Create a purchase order with a UoM of pack of 6 (or some multiples of the Units UoM). 3. Confirm the PO and receive the products. 4. Go to the accounting app, reviews>bill to receive 5. Notice the po line on bill to receive as an incorrect amount. opw-6305324 Forward-Port-Of: odoo/odoo#275876 Forward-Port-Of: odoo/odoo#270327
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per
Original PR description
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per the latest Worldline documentation, ensuring payment requests use the correct mapping. Forward-Port-Of: odoo/odoo#275881
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a barcode for the product with the B variant only - Go to the PoS, enter the barcode for the product with the B variant - The price is 1400 instead of 1200 **Why the fix:** The extra price for dynamic variants ordered through the barcode will be counted twice. This is because it is first count
Original PR description
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a…
**Steps to reproduce:** - Create a dynamic variant with 2 values, A and B - B should have an extra price of 200 - Create a product which has those two variants, with a price of 1000 - Set up a barcode for the product with the B variant only - Go to the PoS, enter the barcode for the product with the B variant - The price is 1400 instead of 1200 **Why the fix:** The extra price for dynamic variants ordered through the barcode will be counted twice. This is because it is first counted in the _scan(code) method when we fetch the product from the models, then counted again when adding the line to the current order. https://github.com/odoo/odoo/blob/f4d079cc5a9c47672cf1a6747bb073e8e74f7350/addons/point_of_sale/static/src/app/services/pos_store.js#L1264-L1269 This step is necessary for the usual flow without the barcode as we need to add this extra price, but when using the barcode, the list price of the product we fetch is already 1200, as the extra price is already included when fetching it from the backend. It works for always attributes because we explicitly check that we are not adding the extra price again in the above code, and that the list price already includes the extra price. It also works for the never attributes because values.product_id.product_template_variant_value_ids.length is 0, so the code to update the extra price is never triggered. As we still need to add the extra price for the usual flow, we now just check if we have a code, meaning we added the product through the barcode and that we do not need to add it again, as the list price already accounts for the extra price. opw-6328600 Forward-Port-Of: odoo/odoo#272395
4 changes
Enhancements to existing features
LEGAL REQUIREMENTS - As of January 2026, the 9% VAT will increase to 12%. PURPOSE - For each 9% VAT, add 12% VAT with the same tax tag and descriptions, so in the VAT report, it's put under the same lines. - And add the missing taxes from the sheet provided in the task description. Related PR: https://github.com/odoo/enterprise/pull/101773 Task-5269617 Forward-Port-Of: odoo/odoo#239388
Original PR description
LEGAL REQUIREMENTS - As of January 2026, the 9% VAT will increase to 12%. PURPOSE - For each 9% VAT, add 12% VAT with the same tax tag and descriptions, so in the VAT report, it's put under the same lines. - And add the missing taxes from the sheet provided in the task description. Related PR: https://github.com/odoo/enterprise/pull/101773 Task-5269617 Forward-Port-Of: odoo/odoo#239388
Resolved issues and error corrections
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per
Original PR description
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per the latest Worldline documentation, ensuring payment requests use the correct mapping. Forward-Port-Of: odoo/odoo#275881
Issue: ---------------------------------------- The units (day, year, etc.) aren't being translated in the Milestones view. Steps to reproduce: ---------------------------------------- - Switch the language to French - Go on an Accrual plan form view - In the milestones view, the units aren't translated Cause: ---------------------------------------- We input the key value of the selections fields `start_type` and `added_value_type`. These values aren't translated. Solution: --
Original PR description
Issue: ---------------------------------------- The units (day, year, etc.) aren't being translated in the Milestones view. Steps to reproduce: ---------------------------------------- - Switch the language to French - Go on an Accrual plan form view - In the milestones view, the units aren't translated Cause: ---------------------------------------- We input the key value of the selections fields `start_type` and `added_value_type`. These values aren't translated. Solution: ---------------------------------------- We create a dictionary with the same keys as the fields and a translated value as values. In the view, we read the values of the dictionary to get the translated units. opw-6367235 Forward-Port-Of: odoo/odoo#275575
Miscellaneous changes
During the _run_average_batch(), we call _get_value() on each dropship move on which an AVCO product is used. In this function, if the following condition is met, we call the function _get_manual_value(): https://github.com/odoo/odoo/blob/12dd03fb678870ddd3f1f8dca66aa3f934aa7985/addons/stock_account/models/stock_move.py#L359-L361 This method's goal is to search product.value records related to the current move. https://github.com/odoo/odoo/blob/12dd03fb678870ddd3f1f8dca66aa3f934aa7985/a
Original PR description
During the _run_average_batch(), we call _get_value() on each dropship move on which an AVCO product is used. In this function, if the following condition is met, we call the function…
During the _run_average_batch(), we call _get_value() on each dropship move on which an AVCO product is used. In this function, if the following condition is met, we call the function _get_manual_value(): https://github.com/odoo/odoo/blob/12dd03fb678870ddd3f1f8dca66aa3f934aa7985/addons/stock_account/models/stock_move.py#L359-L361 This method's goal is to search product.value records related to the current move. https://github.com/odoo/odoo/blob/12dd03fb678870ddd3f1f8dca66aa3f934aa7985/addons/stock_account/models/stock_move.py#L431-L447 This search is performed once per move selected previously even if they are not related to any product.value. We propose to cache the id of every move that is linked to at least one product.value to ensure the search method is only performed for those and potentially reduce the number of calls to the search method. Benchmark ------------ Reducing the execution time with this modification supposes that the majority of stock.move records are not linked to any product.value, which is usually the case. The following benchmark shows the execution times of _run_average_batch() depending on that. | No stock.move | No of moves linked to product.value | Before PR | After PR | |---------------|-------------------------------------|-----------|----------| | 100 | 10 | 1.03 s | 421 ms | | 1000 | 100 | 7.13 s | 1.14 s | | 10000 | 100 | 57.21 s | 1.55 s | | 10000 | 1000 | 60.42 s | 8.98 s | When every stock.move is linked to a product.value, the modification will introduce more operations than needed and slow down the execution. The following benchmark illustrates that. | No stock.move | Before PR | After PR | |---------------|-----------|----------| | 100 | 1.14 s | 1.15 s | | 1000 | 8.21 s | 8.37 s | | 10000 | 80.64 s | 81.51 s | opw-6050007 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#257619
1 change
Resolved issues and error corrections
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per
Original PR description
opw-6368979 Description of the issue/feature this PR addresses: Update the Worldline Cofidis payment method mapping to match the latest payment product ID defined in the Worldline documentation. Current behavior before PR: The Cofidis payment method was mapped to the outdated payment product ID (3012), causing payment requests to use an incorrect mapping. Desired behavior after PR is merged: The Cofidis payment method is mapped to the correct payment product ID (5129) as per the latest Worldline documentation, ensuring payment requests use the correct mapping. Forward-Port-Of: odoo/odoo#275881
58 changes
New functionality added to Odoo
Adds the official Latvian VAT report attachments for domestic, EU purchase, domestic sales/export, and EU sales transactions. Businesses can now review more detailed VAT breakdowns and export the report package in XML for filing or compliance workflows.
Original PR description
This commit adds 4 attachments to the Latvian tax report and an XML export for the tax report (including the attachments). The attachments are the following - PVN 1-I: domestic purchase / import -…
This commit adds 4 attachments to the Latvian tax report
and an XML export for the tax report (including the attachments).
The attachments are the following
- PVN 1-I: domestic purchase / import
- PVN 1-II: EU purchase
- PVN 1-III: domestic sales / export
- PVN 2: EU sale
The attachments give more details for the tax report.
The lines of the attachments are "transactions"
A "transaction" is identified by the move and the transaction type or document type.
The transaction type is given via a tax tag (see community PR).
- PVN 1-I: transaction type, move
- Small transactions (< 150€) are aggregated separately under transaction types 'V' or 'T'
independently of the move
- 'V': All small transactions of a partner in case the total of all their small transactions reaches 150€
- There is max 1 line per partner
- 'T': All small transactions that are not grouped under some 'V' line
- There is max 1 line like this; it has no partner information
- PVN 1-II: transaction type, move
- Small transactions (< 150€) are aggregated separately under transaction types 'V' or 'T'
(like PVN 1-I)
- PVN 1-III: document type, move and line in the main tax report
- All transactions with (document) type 'X' are aggregated on a single line
- Small transactions (< 150€) are aggregated separately under document types 'V' or 'T'
(like PVN 1-I)
- The line in the main tax report is ignored for 'X' and small transactions
- PVN 2: transaction type, move
- No aggregation is performed here
Only account move lines that are tagged with a transaction type (1-I, 1-II, 2)
or a relevant tag for the main report (1-III) are shown in the reports.
The tags `Rep` and `C (car)` only take 40% and 50% respectively of the
base amounts. The tax amount is assumed to be split correctly.
task-4251184
Forward-Port-Of: odoo/enterprise#84135Mexican payroll users can now see key salary values used in payslip calculations, making it easier to validate results. The integration factor can also be adjusted manually when there is not enough historical data, helping ensure correct IMSS contribution setup for new customers.
Original PR description
The daily salary and the integration factor (`l10n_mx_daily_salary` and `l10n_mx_integration_factor`) are two fields used during the payslip computation. Displaying these fields helps users to validate the calculations. Furthermore, when a new customer configures payslips for the first time, there is no historical data in the database to compute the integration factor automatically. Therefore, it is necessary to make this field editable to allow manual adjustments and ensure correct IMSS contributions. target: master task-6267003
This update improves Odoo's AI assistant by moving response generation and chat naming into background jobs, making conversations feel more responsive and reliable. It also adds background subagents that can work independently and surface approval requests clearly, while fixing chat titles, company context, and topic-loading behavior.
Enhancements to existing features
The payroll pay run card now adapts to the actual space available inside the card, not just the browser window size. This makes the header, progress steps, KPI information, and action buttons behave more predictably on different screen sizes and reduces awkward wrapping or overflow.
Original PR description
The pay run header card was assembled by kanban XML inheritance and its responsive behaviour keyed off `ui.size` (the browser-window breakpoint). Regions shifted from one step to the next, and the…
The pay run header card was assembled by kanban XML inheritance and its responsive behaviour keyed off `ui.size` (the browser-window breakpoint). Regions shifted from one step to the next, and the free space and the buttons collapsed based on the window rather than the card's own width - folding while there was still room and overflowing when there wasn't. Rework it into a single OWL shell (PayrunCard) that owns four regions - name | KPIs | steps | buttons. Per-step views only fill the `payrun_kpis` slot and declare their `current_step`; the name block and step bubbles are declared once and reused. The kanban record owns one ResizeObserver that measures the card's actual width and each region's content width, then resolves the layout in priority order: the name truncates to its floor, the buttons collapse into the overflow menu, and finally the steps stack onto their own full-width row. The decision is recomputed only when the width changes, so toggling the layout - which only changes the height - cannot feed back and flicker at the boundary. task-6259171
Payroll administrators can now view and update the first payroll month directly in Payroll Settings. This makes it easier to correct or adjust the initial payroll setup after it has already been entered from the dashboard warning.
Original PR description
Currently, after set the first month of payroll on the dashboard warning. We can't modify it after nor the the information back. In this PR expected to add the first month of payroll in the Payroll Setting, Therefore, Users can modify after set it. task-6377702
Belgian payroll now handles youth and senior time off as separate categories, making payroll and leave tracking clearer. The update also adds checks to warn when youth time off seniority conditions may not be met and to prevent these allocations while regular paid time off remains available.
Original PR description
This PR: - Splits the youth and senior time off types into two different work entry types. - Adds a warning on the allocation of Youth Time Off if the employee does not have at least 1 month of seniority in the company at the beginning of the validity period for the allocation. - Prevents the allocation of youth or senior time offs if there is still paid time off available. task-6360468
Timesheet entry units are now controlled by timesheet settings instead of company-level settings. This makes time tracking behavior more consistent across related areas such as helpdesk, projects, sales timesheets, dashboards, and timesheet grids.
Original PR description
Adjust the `timesheet_encode_uom_id` to depend on timesheet settings, not from company --- # task cancelled task-5932762
The AI app form views and related controls were reorganized to make AI agents and their sources easier to manage. The update also adds native skills and lets agents update themselves, improving flexibility for businesses using AI workflows.
Spreadsheet screen position and viewport behavior are now managed through a shared store instead of an internal plugin, making the experience more consistent across spreadsheet features. Comment popovers now follow the same scroll behavior as other persistent popovers, reducing inconsistent interface behavior.
Original PR description
The `SheetViewPlugin` and the viewport handling was moved into a store rather than a plugin. This commit make the necessary changes to odoo. The test `Scrolling the viewport should hide the comments popover` was deleted. Other persistent popover would automatically be hidden when scrolling, and re-open if scrolling back. There's no reason to have a different behaviour for comments. Task: 6314784
Restricted website editors will no longer see the AI Assistant as an available editing option when they cannot save page changes. A tooltip now explains why the assistant is unavailable, reducing confusion and setting clearer expectations.
Original PR description
Restricted Editors do not have permission to edit website pages. However, the AI Assistant button remains available, giving the impression that the feature can be used even though any changes cannot be saved. This commit disables the AI Assistant button for users without 'Editor and Designer' access and adds a tooltip explaining why the feature is unavailable Forward-Port-Of: odoo/enterprise#123047
Recurring project tasks are now scheduled around assigned users’ workable days, working hours, leave, and contract dates. This helps teams plan recurring work more realistically while still allowing weekend-based recurrences when the original task was intentionally set on a weekend.
Original PR description
## Previous behavior: Recurrent tasks could still be scheduled on weekends, vacation days, or other non-working days. ## New expected behavior: Recurrent tasks are always scheduled based on the…
## Previous behavior: Recurrent tasks could still be scheduled on weekends, vacation days, or other non-working days. ## New expected behavior: Recurrent tasks are always scheduled based on the workable days and working hours of the users assigned to them. Workable days and hours are determined using the assigned users’ shared calendars. If the assigned users do not share the same calendar, the company calendar is used to resolve scheduling conflicts. If a user is on leave, the recurrent tasks they are assigned to are still scheduled, but the user is temporarily removed from the list of assigned users for the duration of their leave.This allows other individuals to take over the task when the user is on leave. Users are also removed from recurrent tasks when their contract start or end dates fall outside the task schedule since users shouldn't work with outdated contracts. ## Exception: This behavior can be overridden if the original recurrent task was initially scheduled on a weekend day (Saturday or Sunday). In this case, recurrent tasks behave exactly as before and may be scheduled on non-working days. This was made to ensure the end-users could have the final say on this behavior in the case it is unwanted. ## Reference: [task-4796700](https://www.odoo.com/odoo/project/4105/tasks/4796700)
Payroll warning settings can now show the same warning on both dashboards and employee or payroll record pages at the same time. This reduces duplicate setup work and makes important payroll alerts more consistently visible across supported country payroll modules.
Original PR description
Replace the `display_on` selection field with two distinct boolean fields: `display_on_dashboard` and `display_on_model`. This allows a single warning configuration to be displayed on both the dashboard and record views simultaneously, eliminating the need for data duplication. Update the view to show these choices as side-by-side checkboxes. Task: 6267499
Signature requests created from other apps now include the template name alongside the related record name. This makes request names, filenames, and email subjects easier to recognize and less likely to be confused with the signer's name.
Original PR description
When requesting a signature from another app, the request name, filename and email subject only showed the linked record name, which often read as the signer's name. The template name is now added so all three follow the same "<prefix> - <template> - <record>" format. task-6317174 Forward-Port-Of: odoo/enterprise#122963
The AI website assistant now includes added design guidance in its prompts. This should help generate website content with better visual direction and more consistent design recommendations.
Creating a shift from the Attendance Gantt view now uses the employee's expected daily working hours instead of defaulting to a full 24-hour shift. This prevents incorrect overnight shifts and avoids accidentally moving the end date to the next day.
Original PR description
Currently, when creating a new shift from the Gantt view in "Attendance", if the scale is "week" or higher, the shift will have a duration of 24 hours and span from 12:00 AM to 12:00 AM the next day. This will always be wrong, and also shifts the end date by a day. To resolve this issue, now if a new shift is created by clicking on a day (instead of dragging the click to select hours), editing the starting hour will automatically change the end hour to be start + expected hours per day. Task ID:6326685
Belgian payroll now supports restructuring social security reductions for up to three quarters instead of two. A new start date field helps track cases where an employee already received the reduction with a previous employer, improving payroll accuracy and compliance.
Original PR description
**What**: - Restructuring reduction can be received for 3 quarters previously it was only for 2 quarters - There is a chance that the person can get restructuring reduction from previous employer so added a new field 'restructuring_date_start' to know the start date of restructuring reduction task-6344925
The salary calculator now waits to show missing-field errors until users try to configure benefits or copy a link, instead of interrupting them while they are still editing. This makes the offer setup process smoother while still clearly listing required information before key actions can continue.
Original PR description
The salary calculator was showing validation errors while users were still filling in the form. This made the calculator harder to use. With this change: - Do not show validation errors while editing a simulation offer. - When the user clicks "Configure Benefits" or "Copy Link", validate all required fields and show an error listing any missing fields. - Remove the "Optional" placeholder from the employee field since it is required to use these actions. Task-6340556
Mexican payroll CFDI checks have been updated to match version 1.2e requirements. This helps ensure payslip XML data is validated correctly for taxable and exempt earnings, other salary income, and employment subsidy limits before reporting.
Original PR description
**. Perceptions – ImporteGravado / ImporteExento (XML Nodes)** For each Perception node, validate that: If ImporteExento = 0, then ImporteGravado > 0. If ImporteGravado = 0, then ImporteExento > 0. Both values cannot be 0 at the same time. These validations must be applied per Perception node, not at an aggregated level. **. TipoPercepcion = "038" (Other Salary Income) (XML Nodes)** When TipoPercepcion = "038": ImporteExento must always be 0. The amount must be recorded only in ImporteGravado. **. SubsidioCausado (XML Nodes)** Update the validation logic for the SubsidioCausado attribute based on NumDiasPagados: If NumDiasPagados ≤ 31, SubsidioCausado ≤ 628.00 If NumDiasPagados > 31, SubsidioCausado ≤ NumDiasPagados × 0.206 task-5412728 Forward-Port-Of: odoo/enterprise#121304
Hong Kong payroll salary rules have been consolidated so regular and casual employee structures can share common rules instead of maintaining duplicate versions. This reduces configuration complexity and should make payroll support and future updates easier while preserving the differences needed for MPF rules.
Original PR description
Recently, salary rules were updated to support more than one salary structure on a same rule. This change allows us to clean our structures and remove a lot of duplication between regular and casual employees. Both structures are 90% the same, besides MPF rules, so we now can really simplify it to facilitate support and reduce complexity task-6267295
Belgian payroll rules now reflect the legal change effective August 1, 2026: employees with less than six months of service have a one-week notice period whether they resign or are dismissed. This helps employers calculate end-of-collaboration notice durations correctly and consistently, including contracts that span the change date.
Original PR description
Starting from August 01 2026, the legal notice period will change if the employee has been working for their company less than six months: it will only be one week, no matter if the employee quit or was fired. Task: 6365099
Payment check reports now better explain cases where a check is written for less than the invoice total because an early payment discount was applied. This helps users and recipients understand the payment amount and keeps localized payment report layouts aligned.
Original PR description
Previously, the check amount didn't match the applied payment. This makes it clear why the a check for less than the total was written out. Because we change the layout of the payment report in community, we have to update some xpaths here. For MX, a `is_cfdi_signed` block was not migrated because it's dead code. That variable isn't defined anywhere. task-5172527
This update makes deferred account settings appear based on the account type, reducing confusion when configuring accounts. It also adds clearer guidance in the interface so users better understand the deferred option.
Original PR description
*accountant, reports Purpose: Some improvements missed in the initial commit: https://github.com/odoo/enterprise/commit/65ea8b266d8024736bec388425c90d9efd9a8cce will be addressed here. - Changed the deferred_account_id invisibility to be based on the account type since it should not be based on is_deferred as they are not related to each other - Added a tooltip to is_deferred for further clarity task-6293902
Resolved issues and error corrections
This change restores payroll fields that were removed too early, including the refund indicator and beneficiary details for salary attachments. It helps ensure payroll payments and related reports can continue handling beneficiary information while the longer-term design is reconsidered.
Original PR description
In this previous PR (https://github.com/odoo/enterprise/pull/114188) we removed the is_refund flag and, together with it, also the fields related to the beneficiary. This is because there is an onchange method on is_refund that sets the beneficiary bank account for any attachment that is not a refund to False. However, while the removal of is_refund is still in the plans, we want to take back the beneficiary fields and use them even in the case of non-refund attachments. We need to think better about how to remove the is_refund field and structure negative attachments around it, so for now we revert the previous PR. Task: 6376383 Forward-Port-Of: odoo/enterprise#123728
Instagram image posts that hit network delays will now be marked as failed instead of causing a server crash. Users receive clearer failure messages, including guidance to use a smaller image when timeouts occur.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#122406 Forward-Port-Of: odoo/enterprise#112573
Payslips sent by email now show a neutral message saying they were sent, instead of incorrectly saying they were re-sent on the first send. When sending payslips for multiple employees, each payslip now receives only one chatter note, reducing confusion in payroll records.
Original PR description
**Issue:** Clicking Send By Email on a payslip opens the hr.payslip.send.mail wizard. Its action_send() always logs "The payslip has been re-send to the employee." in the payslip chatter, even when…
**Issue:** Clicking Send By Email on a payslip opens the hr.payslip.send.mail wizard. Its action_send() always logs "The payslip has been re-send to the employee." in the payslip chatter, even when the payslip is being sent for the first time. The log call also runs inside the loop over the employees and goes through all the payslips of the wizard on each pass, so when the wizard sends payslips of several employees every payslip gets the same note once per employee. This started with the rework of the wizard in https://github.com/odoo/enterprise/commit/39e0488a7e076ee648b47cc3d1cad41cadfd692e **Fix:** The wizard cannot tell a first send from a resend. There is no field on the payslip that keeps track of a previous send, and the chatter cannot be used for that either because the mail sent automatically on validation can be deleted after sending. The fix changes the log in action_send() to say the payslip has been sent by email, which is true in both cases, and moves it out of the employee loop so each payslip gets exactly one note. **Steps to reproduce:** 1. In Payroll > Configuration > Settings, set "Send payslips to employees" to When Paid and save 2. In Payroll > Payslips, create an off-cycle payslip for an employee, click Compute, then Validate 3. Go back to the settings and set "Send payslips to employees" to When Confirmed 4. On the payslip, click Pay, then Mark as Paid 5. Click Print so the payslip document is generated 6. Click Send By Email and send the mail 7. Check the payslip chatter => The chatter shows "The payslip has been re-send to the employee." while the payslip was never sent before Ticket [link](https://www.odoo.com/odoo/project.task/6324204) opw-6324204 Forward-Port-Of: odoo/enterprise#123298
Chilean export invoice PDFs now keep customs information in the correct columns even when origin or destination port details are missing. This prevents package quantities and other export details from appearing under the wrong headings, improving document accuracy for customers and customs processes.
Original PR description
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by…
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by QWeb, causing the remaining columns to shift left This results in `Qty of Packages` appearing under `Origin Port` or `Destination Port` in the printed document ### Cause: `l10n_cl_port_origin_id` and `l10n_cl_port_destination_id` have no default value and are optional fields `t-out` on a falsy value omits the `td` entirely in QWeb, breaking the column alignment Adding `or ''` ensures an empty `td` is always rendered, preserving the table structure regardless of whether the fields are set ### Steps to reproduce: - Install `l10n_cl_edi_exports` and switch to CL Company - Create an Invoice (any customer, any line) - In the gear menu, select Print > Invoice PDF copy (Chile) Before the fix, `Qty of Packages` appears under `Origin Port` when neither port field is set opw-6304670 Forward-Port-Of: odoo/enterprise#123150 Forward-Port-Of: odoo/enterprise#121923
Belgian termination holiday attest payslips now use the employee's private address directly, so the address is shown correctly in the required places. This helps ensure departing employees receive complete and accurate payroll documents.
Original PR description
[FIX] l10n_be: missing employee address on holiday attest Bug reproduction: Belgium -> create employee -> fire the employee -> look to the holiday attest payslips (N and N-1) -> private address of the employee is missing in 2 places in payslip Bug cause: o.employee_id.work_contact_id work contact id was used in report but we can just use private_street, private_city etc. instead. Bug solution: Use private_street, private_city etc. fields directly from the employee model. task - 6361457 Forward-Port-Of: odoo/enterprise#123528
This fixes an installation blocker for the Peruvian electronic invoicing localization caused by a typo in an internal database query. Businesses using or enabling Peru localization can install the module successfully again.
Original PR description
A refactor/cleanup [1] introduced a buggy SQL query preventing the Peruvian localization install. [1]: https://github.com/odoo/enterprise/commit/e182608f13c6eefae11339bba24e80497c2b3903#diff-deaab3f5010fea8defc8af11dc186415ecc9079d86d307537b09222dda7ab751R119 task-none
This update fixes issues in the social CRM and social feed experience where post menus could appear empty, feed refreshes could fail due to timeouts, and LinkedIn image uploads could error. The changes make day-to-day social media management more reliable and reduce interruptions for users working with social posts and leads.
Original PR description
Bug 1 === Since b75755ea8ac65ce5ce973412e3c4194fa1bd6fd3 , the menu on the stream post could be visible but empty. The reason is that we checked for `this.isConvertibleToLead` instead of `this.isConvertibleToLead()`. We take advantage of this bug fix to correctly overwrite the condition without replacing the entire button (which can break other module overwriting the same element). Bug 2 === Sometimes, when refreshing the feed view, an error occurs because the request timeout. To fix it, we increase the timeout when doing requests in batch. Bug 3 === When uploading an image in LinkedIn, an error happens. The reason is that `LocalBinaryFile` is now returned when reading Binary field, and in the requests API, the `data` arguments expect the bytes. (for other media, we upload the image with `file` argument). Task-6254983 Forward-Port-Of: odoo/enterprise#123949 Forward-Port-Of: odoo/enterprise#118329
Subscription product pages now load correctly when a discount is configured directly on a recurring plan without a pricelist. This prevents website errors during price calculation and ensures customers see the intended discounted recurring price.
Original PR description
**Problem:** On the website, a subscription product page returns a 500 error when a discount is set directly on the recurring plan (a time-based pricing rule with a plan but no pricelist). **Steps to…
**Problem:** On the website, a subscription product page returns a 500 error when a discount is set directly on the recurring plan (a time-based pricing rule with a plan but no pricelist). **Steps to reproduce:** 1. Create a subscription product with a recurring plan. 2. Add a recurring price rule for that plan with no pricelist, set as a percentage discount (base = sales price). 3. Open the product page on the website. **Current behavior:** The page fails with a 500: Internal Server Error during price computation. **Expected behavior:** The page loads and shows the discounted recurring price. **Cause of the issue:** For a recurring price rule based on the sales price, `_compute_base_price` looks up "the no-pricelist rule for the plan" to use as its base, via `_get_applicable_rules_domain(plan_id=...)`. When the discount is set directly on the plan, the rule being computed has no pricelist itself, so that search returns the very same rule and calls `_compute_price` on it again, leading to infinite recursion. **Fix:** Excluding the rule itself from the base-rule lookup lets a no-pricelist plan rule resolve its base from the product's sales price (the super() fallback) instead of re-entering its own computation. A rule applied through a pricelist is unaffected, since its no-pricelist base rule is a different record. opw-6306105 Forward-Port-Of: odoo/enterprise#121466
Fixed an issue where outbound FedEx shipment labels could lose their reference field when return labels were enabled. This helps businesses keep the expected shipment reference visible on original delivery labels while still supporting return labels.
Original PR description
Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. <img width="438" height="148" alt="image" src="https://github.com/user-attachments/assets/42acce7b-6177-4f8f-81d3-ad6dfd3e4bb2" /> Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. Expected outcome (after fix) ---- <img width="428" height="146" alt="image" src="https://github.com/user-attachments/assets/0d22e147-da90-4aa4-b3ca-2d996c7cc147" /> ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#118659
Fixed a conflict that caused Obox quality-control cameras to stop working after the IoT module was installed. Users can continue taking required quality-check photos without seeing a false camera-not-found error, and irrelevant IoT controls are hidden when no IoT device is configured.
Original PR description
Steps to reproduce: - Install `obox_quality_control` but do not install `iot`. - Configure a quality check to take a picture with an Obox camera. - Validate a receipt an confirm the camera works as expected. - Now install the `iot` module, and try to take a picture again. **Expected behaviour:** The camera still works as expected. **Actual behaviour:** There is a 'Camera not found' error. This issue is caused by both the Obox and IoT quality modules adding an `identifier` field to the quality control wizard. The fix is simply to use a different name for the Obox field. In addition, we now hide the IoT button in the wizard if the IoT device is not set. task-6329066 Forward-Port-Of: odoo/enterprise#122490
Fixes an installation and upgrade failure in the Peru electronic invoicing module that could affect databases with existing journal entries. This helps ensure updates complete successfully and required invoice data is filled in correctly.
Original PR description
### Description Installing or upgrading `l10n_pe_edi` aborts with a `psycopg2.errors.SyntaxError` whenever `account_move` already contains rows: ``` psycopg2.errors.SyntaxError: syntax error at or…
### Description
Installing or upgrading `l10n_pe_edi` aborts with a `psycopg2.errors.SyntaxError` whenever `account_move` already contains rows:
```
psycopg2.errors.SyntaxError: syntax error at or near "AND"
LINE 9: AND l10n_pe_edi_operation_type IS NULL
```
### Root cause
The `init_storage` SQL that backfills `l10n_pe_edi_operation_type` (added in e182608f13c6 `[REF] *: use init_storage`) closes the `WHERE` clause with a stray semicolon right after the country condition:
```sql
WHERE res_company.id = account_move.company_id
AND move_type IN ('out_invoice', 'out_refund')
AND res_country.code = 'PE'; -- stray ';' ends the UPDATE
AND l10n_pe_edi_operation_type IS NULL -- parsed as a new statement -> syntax error
```
The semicolon terminates the `UPDATE` early, so `AND l10n_pe_edi_operation_type IS NULL` is parsed as a separate statement starting with `AND`.
`init_storage` only runs when the table already has rows (`_init_column_data` in `odoo/orm/fields.py` skips empty tables), which is why the crash surfaces on databases that already contain journal entries — e.g. runbot `*-all` builds, or `button_immediate_install` over a populated database.
### Fix
Remove the stray semicolon so the NULL guard stays part of the `WHERE` clause.
### Validation
Reproduced and verified on `master` (community + enterprise), with a row present in `account_move`:
- **Before:** `-u l10n_pe_edi` fails with `syntax error at or near "AND"` at `LINE 9`.
- **After:** the module installs/updates cleanly and the column is backfilled without error.Payroll runs now correctly identify when expected payslips are missing. This ensures payroll teams receive the right warning and can address gaps before processing payroll.
Original PR description
The missing payslip in a payrun warning wasn't triggered correctly because we were filtering on the schedule pay of the payrun and this field was removed in a previous PR. task-6329134 Forward-Port-Of: odoo/enterprise#121641
Sales commission plans now reject salesperson start dates that fall outside the plan's effective period. This prevents invalid commission setup and helps ensure salespeople are assigned only within eligible plan dates.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#122870 Forward-Port-Of: odoo/enterprise#118289
Twitter replies are now blocked in Odoo when the account is not allowed to respond, such as when the tweet does not mention the account or quote one of its tweets. This prevents failed or inappropriate automated replies and helps avoid unwanted outreach to Twitter users.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524
Canadian EFT batch payment exports now use each payment's ID as the Item Trace Number instead of filling it with zeros. This helps ensure files comply with CPA-005 banking rules and avoids payment rejections by Canadian financial institutions.
Original PR description
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as…
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as a zero-filled sequence According to CPA-005 standards on the Item Trace Number: "The data elements (b), (c) and (d) each must be greater than zero or the TRANSACTION WILL BE REJECTED" (page 36). https://www.payments.ca/sites/default/files/standard005eng.pdf Steps to reproduce: 1. Install the module l10n_ca_payment_cpa005 2. Go into "CA Company" 3. In the configuration for "CA Company", add something to the fields "Short Name used in Canadian EFT" and "Company ID" i.e. "CCC" 4. Set all the fields in the "Canadian EFT/CPA Configuration" section of the bank journal 5. Set the bank record on the bank journal. Set the field "Financial Institution ID Number" field of the "Account Number" record of the bank journal to any numerical sequence 6. Create a bank account on "Azure Interior" and make sure to check the field to trust the bank account that you created (otherwise there will be an error) 7. Create two payments with the vendor of "Azure Interior" using the payment method of "Canadian EFT" 8. Create a batch payment for both payments created 9. Validate the batch payment and the export file should show up in the chatter 10. Note that in the export file, the Item Trace Number for each payment is set to be all zeros, whereas it should be a nonzero identification sequence Solution: Set the Item Trace Number to be the payment's id opw-6323432 Forward-Port-Of: odoo/enterprise#124016 Forward-Port-Of: odoo/enterprise#123633
The timesheet assistant now captures time spent in Odoo applications even when the activity cannot be linked to a specific project, task, or ticket. This helps users get more complete time suggestions, with these activities shown as separate key entries for easier review.
Original PR description
This PR adds support for tracking time spent in the Odoo apps in the assistant, for when we can't trace URLs to a project/task/ticket. The activities detected this way are marked as key events, such that each appears as an individual line in the assistant suggestions. With this, most of the time users spend working in their Odoo database should be reflected in the assistant suggestions. Task-6250449 Forward-Port-Of: odoo/enterprise#123147 Forward-Port-Of: odoo/enterprise#119096
The database authentication module was added to the translation workflow so translators can provide localized text. The update also corrects wording mistakes and tidies an internal error check, improving clarity with minimal user impact.
Original PR description
The aim of this commit is to allow the translator to work on this module translation and fix a typo that was made. Task-id: None Forward-Port-Of: odoo/enterprise#124038
Printing an appraisal form from the action menu now waits briefly so the menu can close first. This prevents the dropdown from appearing on the printed document, giving users a cleaner and more professional printout.
Original PR description
When printing the appraisal form from the action (cog) menu, the drop down menu itself was incorrectly showing up in the printed document. This happened because the browser started printing immediately before the menu had time to close. By adding a small delay before triggering the print action, the menu now has time to completely close, so it no longer appears in the final print. task-6369240 Forward-Port-Of: odoo/enterprise#123242
This update corrects a database query issue in the Peru electronic invoicing module. It helps prevent errors when processing accounting documents, improving reliability for affected users.
This update improves manufacturing work order planning by showing planned work orders by default and aligning shop floor card options with company settings. It also corrects engineering change cost calculations so bill of materials cost differences better reflect real operation cost changes.
Original PR description
Forward-Port-Of: odoo/enterprise#122639
Fixes an issue where the cursor could jump backwards while users typed in Studio's XML editor. The editor now keeps cursor position reliably per editing session, making report and view editing smoother and less disruptive.
Original PR description
Steps to reproduce the issue: -> Open studio -> Edit any view -> Edit xml => Cursor moves backwards when typing Some components inside of the report editor were managing the cursor position based on the document manually. Rendering timings could cause the cursor to move while typing. This commit internalizes the cursor position in the CodeEditor and keep track of them based on the sessionsId, making sure that the cursor position is always correct and only changing when switching between sessions while also making the component API simpler. Community: https://github.com/odoo/odoo/pull/274681 Forward-Port-Of: odoo/enterprise#123244
This change updates an accounting reports screen so it continues to work with the latest underlying interface framework. It prevents a compatibility issue that could affect the display or behavior of the account return check kanban view.
Original PR description
The previous code worked because owl was too permissive.
Mexican payroll payslip forms no longer crash when users add Daily Salary or Integration Factor fields with Odoo Studio. This helps payroll teams review salary-related calculations safely, including while creating off-cycle payslips before an employee is selected.
Original PR description
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule…
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule computations. However, doing so raises a traceback immediately upon closing the Studio editor, as well as when attempting to create a new Off-Cycle payslip.
### Steps to reproduce:
* Install `l10n_mx_hr_payroll` and `web_studio`.
* Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company.
* Go to Payroll > Payslips > Payslips and create a "New Off-Cycle"
* Use the Studio editor to add `l10n_mx_daily_salary` or `l10n_mx_integration_factor` fields.
* Close the Studio editor.
### Current behavior:
A traceback is raised depending on the field added
#### For the Daily Salary field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 21, in _compute_daily_salary
payslip.l10n_mx_daily_salary = payslip.version_id.wage / payslip._rule_parameter('l10n_mx_schedule_table')[payslip.version_id.schedule_pay]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: False
```
#### For the Integration Factor field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 33, in _compute_integration_factor
payslip.employee_id.with_context(before_date=payslip.date_from)._get_first_contract_date()
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 493, in _get_first_contract_date
versions = self._get_first_versions_filtered(no_gap=no_gap).filtered(lambda x: x.contract_date_start)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 461, in _get_first_versions_filtered
self.ensure_one()
File "/Users/ivgm/odev/worktrees/19.0/odoo/odoo/orm/models.py", line 5942, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: hr.employee()
```
### Expected behavior:
No error is raised, and the fields are correctly displayed on the form view.
### Solution:
* Add Guard Clause: When creating a "New Off-Cycle" payslip, `payslip.version_id` is not initially set because no employee has been selected yet. Added a condition to check if `version_id` exists before computing the values to prevent the traceback.
* View Update: Since displaying these fields is a highly requested feature for traceability, they have now been added to the form view.
target: 19.0
task-6267003
Forward-Port-Of: odoo/enterprise#121718The attendance Gantt view now hides empty parentheses in progress bar labels when there is no extra information to show. This removes confusing visual clutter and makes attendance planning information easier to read.
Original PR description
The label should not display empty parenthesis if there is no extra info to display task-6391439
Point of Sale receipts will no longer include the separate terminal receipt generated by Worldline payments. This keeps customer receipts cleaner and avoids redundant payment information being printed or shown.
Original PR description
This PR removes the terminal receipt from Worldline we are currently inserting in the Point Of Sale receipt We don't adapt the driver code to get the receipt as we cannot change C method prototypes task-6373975 Forward-Port-Of: odoo/enterprise#123770
The payroll payrun chatter panel and button are now limited to the correct payrun screens. This prevents confusing extra options from appearing in unrelated payroll views, giving users a cleaner and more predictable experience.
Original PR description
The global `PayRunChatterService` was leaking state across shared views, causing the chatter panel and button to appear on views accessed outside the PayRun layout (e.g., via the main Payroll > Time Offs menu). Fix this by introducing a `useEffect` hook in `PayRunLayout` that checks for a valid `payrun_id` or `payRunReactive` state on view render. If absent, the chatter service state is explicitly reset and closed. The control panel button is also wrapped in a contextual `t-if` check, fully isolating the feature to its intended screens. Task : 6347871 Forward-Port-Of: odoo/enterprise#123570
Employees and managers can now request and save appraisals even when the scheduled appraisal date has already passed. This removes an unnecessary error that blocked late appraisal requests and avoids requiring users to manually adjust dates they may not have permission to change.
Original PR description
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings,…
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings, set Next Appraisal Date to tomorrow and wait for 2 days Then : - Click on Request Appraisal - Save # The problem An error is shown saying "You cannot set 'Next Appraisal Date' in the past.". You can workaround this by changing the Next Appraisal Date to a date in the future, but the problem is not every user has the right to do this. # Cause `next_appraisal_date` is also defined in hr.appraisal as a relate field of hr.employee : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_appraisal.py#L56-L57 When creating an hr.appraisal, `next_appraisal_date` is present in `vals_list` because it is defined in the view since : https://github.com/odoo/enterprise/commit/58fba3098f33db82dfbccca2db229550402ed3ab https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/views/hr_appraisal_views.xml#L92 This triggers a write on `next_appraisal_date` of hr.employee which triggers a constraint : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_employee.py#L81-L85 opw-6147865 Forward-Port-Of: odoo/enterprise#123817 Forward-Port-Of: odoo/enterprise#114876
Payroll start warnings now include the evaluation logic needed to determine when they should appear. This helps payroll teams receive the right warning before starting a pay run, reducing confusion and the risk of missed checks.
Original PR description
In this commit, we finxed the definition of start payrun warning to include the evaluation code in the warning definition. task-6179707
Rental planning now only blocks resources for company-wide leave when that leave applies to their working calendar, preventing unnecessary allocation conflicts. The update also strengthens related rental planning website and backend tests to help keep booking behavior reliable.
Original PR description
## [FIX] sale_renting_planning: check global leaves working schedule Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated…
## [FIX] sale_renting_planning: check global leaves working schedule
Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated during the leave date.
After this commit: any `resource.calendar.leaves` with `no resource_id` would be applied only to resources with the same `calendar_id` as the leave.
if the leave has no `calendar_id` then the leave applies to all `resource.calendars`
if a resource has no `calendar_id` then leaves with no `calendar_id` apply to it as well
## [IMP] {website_}sale_renting_planning: move tests from industry and fix existing ones
This commit moves the tests from [odoo/industry#1980](vscode-file://vscode-app/snap/code/237/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) to their respective standard modules.
It also fixes the logic behind some tests as they weren't testing a `planning.role` with `sync_shift_rental` enabled.
task-6179505
Forward-Port-Of: odoo/enterprise#120983
Forward-Port-Of: odoo/enterprise#116430Belgian payroll pay runs no longer fail when an employee has multiple contract or work schedule versions within the same month. This ensures payslips can be generated reliably for employees with mid-month changes, reducing payroll processing interruptions.
Original PR description
Currently, there is an error while running payrun step with employee who has multiple version in 1 month. ``` number_of_hours = (work100_wds - worked_day).number_of_hours ValueError: Expected singleton: hr.payslip.worked_days(233, 234) ``` Step to reproduce: 1. Create Employee with multiple version in 1 month 2. Create New PayRun during that month 3. Run the PayRun until Payslip step 4. Expected error on payslip steps reason: substraction of work100_wds and worked_day generate more than 1 value, if we have multiple version in 1 month task-6296276 Forward-Port-Of: odoo/enterprise#122723 Forward-Port-Of: odoo/enterprise#122483
This update fixes several issues around how taxes are calculated and stored when documents switch tax modes. It improves consistency for invoices, purchases, sales, and Italian electronic invoice imports, reducing the risk of incorrect totals or validation issues.
Original PR description
- changing python constraint on document tax mode on account.move to SQL - style enhancements to the overlap_badge_tab and new component - removing inconsistent rounding in purchase.order - adding document tax mode logic to account.tax compute_all method - adding missing document tax mode ‘tax_excluded’ setting to l10n_it_edi during account.move creation of imported invoices odoo/odoo/pull/272730 Following up: https://github.com/odoo/odoo/pull/251800 Forward-Port-Of: odoo/enterprise#122246
Sendcloud shipping labels now correctly handle delivery addresses where the house number contains a dot, such as “12.345”. This prevents incorrect address data from being sent to the carrier and helps avoid malformed labels or delivery issues.
Original PR description
Issue ----- Labels have unexpected format when the delivery address has a dot (`.`) in the number. Steps to reproduce ----- - Set up Sendcloud (carrier shouldn't matter) - Enable logs - Create a customer (with valid address, phone and email) - Address must contain a dot, eg Grand Place 12.345 - Deliver a product to the customer - Add sendcloud as delivery method - Go to the logs - Open the "sendcloud request parcels" log > house_number is 12 Cause ----- The `house_number` field is populated using `_get_house_number`, where the regex used to extract the number from the address line does not accept the `.` character. https://github.com/odoo/enterprise/blob/f93882555864a1f0a2a3e3863780096c78923bfa/delivery_sendcloud/models/sendcloud_service.py#L323 ----- Ticket: opw-6295904 Forward-Port-Of: odoo/enterprise#123820 Forward-Port-Of: odoo/enterprise#123266
Features or functions removed from Odoo
Odoo is removing an obsolete report setting that is no longer used to generate QWeb reports. Reports now rely on the existing report name setting, reducing redundant configuration with no expected change to normal reporting behavior.
Original PR description
The `report_file` field on `ir.actions.report` is no longer used by the QWeb reporting engine. QWeb reports rely on `report_name` to locate and render the template. This commit removes this redundant field from report actions. Community PR:- https://github.com/odoo/odoo/pull/275521 Upgrade PR:- https://github.com/odoo/upgrade/pull/10750
Belgian payroll calculations are updated so employees in Brussels no longer receive the elderly worker reduction starting in Q3 2026. This keeps payroll results aligned with the regional rule change and updates validation tests accordingly.
Original PR description
removed the reduction for everyone in BXL starting Q3 2026 and adapted the tests task - 6331080 Forward-Port-Of: odoo/enterprise#123921
Code cleanup and technical improvements
The payroll module received an internal technical update to stay compatible with the latest Odoo web interface framework. This helps keep payroll screens reliable and maintainable without changing day-to-day user workflows.
Original PR description
As part of the Owl 3 migration, replace onWillUpdateProps hook with the appropriate Owl 3 alternatives.
This update modernizes internal Studio code by replacing a deprecated technical component with newer supported alternatives. It helps keep Studio easier to maintain and reduces future upgrade risk, without changing visible business functionality.
Original PR description
This commit removes the use of the deprecated 'useComponent' hook to use other more appropriate Owl features instead.
11 changes
Enhancements to existing features
The journal creation wizard can now be navigated with keyboard arrow keys, making setup faster and easier for users who prefer keyboard workflows. This improves accessibility and efficiency during accounting configuration without changing the underlying process.
Original PR description
This commit aims to allow for navigation through the journal create wizard via keybaord arrows. Related Odoofin PR: https://github.com/odoo/odoofin/pull/502 task-5796200
The French balance sheet now presents establishment costs before fixed assets, matching the expected reporting structure. It also includes previously missing impairment accounts for tangible fixed assets, improving the completeness and accuracy of financial statements.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138
Resolved issues and error corrections
This fixes an internal payroll issue where reused rule settings could be unintentionally altered during calculations. Payroll rules now receive a safe copy of these settings, reducing the risk of inconsistent or hard-to-trace payroll results.
Original PR description
Cached functions with `@ormcache` should not return immutable values, yet `_get_parameter_from_code()` could return dicts/sets/lists/etc. It could lead to very obscure bugs such as: ```python def…
Cached functions with `@ormcache` should not return immutable values, yet `_get_parameter_from_code()` could return dicts/sets/lists/etc.
It could lead to very obscure bugs such as:
```python
def some_innocent_code():
category_dict = self.env["hr.rule.parameter"]._get_parameter_from_code('l10n_be_work_entry_categories')
incapacity_codes = category_dict['partial_incapacity']
incapacity_codes |= category_dict['total_incapacity']
# ... then use incapacity_codes
def print_rule_param():
print(self.env["hr.rule.parameter"]._get_parameter_from_code('l10n_be_work_entry_categories')['partial_incapacity'])
print_rule_param() # OrderedSet(['LEAVE281'])
some_innocent_code()
print_rule_param() # OrderedSet(['LEAVE281', 'LEAVE264', 'LEAVE266', 'LEAVE217', 'LEAVE218', 'LEAVE219', 'MEDIC01'])
```
The solution was to either deepcopy the returned value each time, or to change all the rule parameters to their frozen equivalent. Since we don't have access to frozen objects in rule parameters's xml definitions, we opted for the deepcopy approach.
task-6329380
Forward-Port-Of: odoo/enterprise#124141
Forward-Port-Of: odoo/enterprise#123057This fix ensures the express mention in French VAT report files is placed in the correct part of the submission sent to Aspone. This helps avoid rejection or processing issues caused by the mention being included in an unsupported section.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745
Opening Studio from a project task list now keeps the browser address clean and correctly tracks the active project context. This prevents errors when users go back in the browser or open a Studio URL directly.
Original PR description
Go on a project, then open its task list view Open studio with the menu item. At this point, studio is open but the url looks like: `/odoo/project/5/tasks/studio/5` the last `/5` is wrong ; this commit fixes this. Then, hit the browser's back button. There is an error because the active_id was not correctly set when leaving studio that way Try loading `/odoo/project/5/tasks/studio`, again, there is an error because the active_id is read from the wrong object Forward-Port-Of: odoo/enterprise#122405
When a new employee contract is created from a template, its analytic distribution is now copied correctly. This prevents missing payroll cost allocation information and reduces the need for manual correction after contract creation.
Original PR description
Problem: When creating a new contract from a template, the analytic distribution field is not copied from the template to the contract. Steps to reproduce: 1. Create a contract template with an analytic distribution. 2. Create a new contract for an employee from the template. 3. Check the analytic distribution field on the new contract. 4. Notice how the analytic distribution field is empty, even though it was set on the template. Cause: The field is not included in the list of whitelisted fields to copy from the template. https://github.com/odoo/odoo/blob/0133e46f89df7dce8c39d2bacd29579d57a83fad/addons/hr/models/hr_version.py#L443 opw-6370781
This fixes a display issue where the CFDI Origen field could disappear from Mexican invoice forms when the Colombian e-invoicing module was also installed. Users working with Mexican electronic invoicing can now reliably access the needed field without module conflicts.
Original PR description
The field 'CFDI Origen' (l10n_mx_edi_cfdi_origin) is not visible on the account move form view if l10n_co_edi module is installed because this https://github.com/odoo/enterprise/blob/19.0/l10n_co_edi/views/account_invoice_views.xml#L10 is the last group on ="//sheet/group//group[last()]" and it is invisible for mx. This commit fixes that. I created this issue https://github.com/odoo/odoo/issues/276358 reporting the bug. Task Adhoc side: 67269
Opening transfers in the barcode app now applies a default limit when loading reusable packages. This prevents very large package lists from causing long waits, improving usability for warehouses with high package volumes.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730
Bank reconciliation now correctly shows exchange rate adjustment entries again. This helps accounting teams review and match foreign-currency transactions accurately without missing related exchange movements.
Original PR description
Fix a bug where the exchange moves are no more displayed in the bank reco widget. Bug introduced here: https://github.com/odoo/enterprise/pull/119557 no-task
Kitchen preparation orders now keep their place when staff mark individual order lines, avoiding confusing reordering after a page reload. Orders only move to the back when they actually change preparation stage, making the display more predictable for restaurant teams.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046
Miscellaneous changes
1 change
Resolved issues and error corrections
Steps to reproduce: - In Outlook, create a recurrence with an exception that is not the first occurrence. - Run the Microsoft calendar synchronization in Odoo. - The exception is imported without microsoft_id or ms_universal_event_id, and follow_recurrence is set to True. Outlook exceptions are converted without their identifiers, and calendar.event creation overwrites their explicit follow_recurrence=False value. Preserve both the Microsoft identifiers and the detached exception state dur
Original PR description
Steps to reproduce: - In Outlook, create a recurrence with an exception that is not the first occurrence. - Run the Microsoft calendar synchronization in Odoo. - The exception is imported without microsoft_id or ms_universal_event_id, and follow_recurrence is set to True. Outlook exceptions are converted without their identifiers, and calendar.event creation overwrites their explicit follow_recurrence=False value. Preserve both the Microsoft identifiers and the detached exception state during import. opw-5129848