Daily updates from Odoo
Monday, August 10, 2026
197 changes
14 changes
Resolved issues and error corrections
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/file
Original PR description
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/files/formulaires/3310-ca3-sd/2026/3310-ca3-sd_5426.pdf ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: E5 and F3) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, E5 and F3 lines are empty opw-6357703 Forward-Port-Of: odoo/odoo#278635
Changing options for the Contact Us button in the navbar makes the button lose current selection.
Original PR description
Changing options for the Contact Us button in the navbar makes the button lose current selection.
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Original PR description
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
_track_finalize() can browse records into self that get dropped from trackings when _mail_track() raises MissingError (e.g. deleted mid-transaction), so indexing trackings[move.id] could KeyError. Iterate trackings.items() instead, since it's the authoritative set of records with tracking data. runbot-944656 Forward-Port-Of: odoo/odoo#281110
Original PR description
_track_finalize() can browse records into self that get dropped from trackings when _mail_track() raises MissingError (e.g. deleted mid-transaction), so indexing trackings[move.id] could KeyError. Iterate trackings.items() instead, since it's the authoritative set of records with tracking data. runbot-944656 Forward-Port-Of: odoo/odoo#281110
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the corresponding Purchase Orders, then confirm the merged PO 4. Validate the dropship transfer Issue stock.picking.sale_id is a Many2one (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/sale_stock/models/stock.py#L99) computed from procurement.group.sale_id, an
Original PR description
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the…
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the corresponding Purchase Orders, then confirm the merged PO 4. Validate the dropship transfer Issue stock.picking.sale_id is a Many2one (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/sale_stock/models/stock.py#L99) computed from procurement.group.sale_id, and stock.picking.group_id is a stored related on move_ids.group_id (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/stock/models/stock_picking.py#L186). A single picking can therefore only resolve to one SO. _create_picking (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/purchase_stock/models/purchase_order.py#L290) builds one picking per PO and _prepare_stock_moves assigns every move the merged PO's group_id (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/purchase_stock/models/purchase_order_line.py#L307), so when a merged dropship PO carries lines from multiple SOs every move lands in one picking under the PO group. Only one SO gets linked and the others stay "not fully delivered" even after validation. Solution Override PurchaseOrderLine._prepare_stock_moves to set group_id to the SO's procurement_group_id when sale_line_id is set, so each dropship move is created in its originating SO's procurement group. Override PurchaseOrder._create_picking to detect dropship POs whose order lines span more than one SO and create one picking per SO group by calling _prepare_picking and _create_stock_moves per group. picking.group_id then resolves to the SO group via the stored related field, picking.sale_id points to the right SO, and delivery_status updates correctly on validation. opw-6094608 Forward-Port-Of: odoo/odoo#280166 Forward-Port-Of: odoo/odoo#257823
This commit will remove the condition about the review state to place the move in to review. We want to place the move in the state "to_review" as soon as a user with not enough access right modify the move. task-6409437 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278078
Original PR description
This commit will remove the condition about the review state to place the move in to review. We want to place the move in the state "to_review" as soon as a user with not enough access right modify the move. task-6409437 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278078
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5 karma (to give him enough rights to answer and comment) - Connect with the portal user and go to the post - Create an answer - Try to comment on your own answer - AccessError is raised **Issue:** Since [1] we check comodel access (in this case `res.partner`) when adding records. Here
Original PR description
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5…
**Steps to reproduce:**
- Install website_forum
- Create a new post on the forum with the admin
- Subscribe to the post notifications using the bell button
- Create a new portal user and give him 5 karma
(to give him enough rights to answer and comment)
- Connect with the portal user and go to the post
- Create an answer
- Try to comment on your own answer
- AccessError is raised
**Issue:**
Since [1] we check comodel access (in this case `res.partner`) when adding records. Here during the `message_post` the `question_followers` are added manually as `partner_ids` before sending (the logic only relies on the original post subscribers, not on the added comment/reply).
```py
question_followers = self.env['mail.followers'].sudo().search([
('res_model', '=', self._name),
('res_id', '=', self.parent_id.id),
('partner_id', '!=', False),
]).filtered(lambda fol: comment_subtype in fol.subtype_ids).mapped('partner_id')
partner_ids += question_followers.ids
```
As the portal user has no `read` access to the subscribers the message creation fails with a traceback.
**Fix:**
Add `sudo` to the `message_post` call of `post_comment`.
(Also fix a minor display issue in the 'Karma Error' notification)
[1] https://github.com/odoo/odoo/commit/aae732957c3c3b3590f5686cfccc0ab264d0b5c9
opw-5318757
Forward-Port-Of: odoo/odoo#279607
Forward-Port-Of: odoo/odoo#274751# How to reproduce - Create a product with a tag that is not visible to customers - Go to the website shop page - Search for the tag's name # The issue The product & the tag are displayed even though they should be invisible to customers # Cause This commit introduced the search on tags : https://github.com/odoo/odoo/commit/9394e17a07cb125914fba137405c152bee2d7618 It did by simply adding `product_tag` to the fields searched by the autocomplete : https://github.com/odoo/odoo/blo
Original PR description
# How to reproduce - Create a product with a tag that is not visible to customers - Go to the website shop page - Search for the tag's name # The issue The product & the tag are displayed even though…
# How to reproduce - Create a product with a tag that is not visible to customers - Go to the website shop page - Search for the tag's name # The issue The product & the tag are displayed even though they should be invisible to customers # Cause This commit introduced the search on tags : https://github.com/odoo/odoo/commit/9394e17a07cb125914fba137405c152bee2d7618 It did by simply adding `product_tag` to the fields searched by the autocomplete : https://github.com/odoo/odoo/blob/9394e17a07cb125914fba137405c152bee2d7618/addons/website_sale/models/product_template.py#L901 The issue is that when building the domain to do the actual search, we simply do a big OR with an ilike search for all the searched fields : https://github.com/odoo/odoo/blob/f8d82f481b575a7a009234d9628fc8c604d0cf22/addons/website/models/mixins.py#L680-L686 # Proposed solution Move the domain creation for search fields in a new function. This allows us to override the simple ilike domain creation and create a custom domain based on the `visible_to_customers` field of tags Furthermore, we also need to prevent the invisible tags from being rendered because a product may contain visible & invisible tags opw-6357064 Forward-Port-Of: odoo/odoo#274022
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Original PR description
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Following odoo/odoo#269253, the dropdown width was set to the input width, which could truncate long items. This commit makes the input width the dropdown's minimum width. Longer items can still expand the dropdown to remain fully visible. Task-6431654
Original PR description
Following odoo/odoo#269253, the dropdown width was set to the input width, which could truncate long items. This commit makes the input width the dropdown's minimum width. Longer items can still expand the dropdown to remain fully visible. Task-6431654
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrol
Original PR description
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist"…
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrolled too far. The same issue happens with similar steps in the following cases: - When using any option using the `addItem` action. - When undoing/redoing a step that was done in an element not in the viewport (the screen will scroll to it and we will have the issue). - When showing an invisible element (the screen will scroll to it if not in the viewport) - Adding a grid item with the "Add Elements" option. - Adding a new card in the "Floating Cards" snippet. The common point to all these cases is that they all scroll to the added or shown element with the `scrollIntoView` built-in function, which scrolls everything, including the viewport. It also doesn't take into account the header that changes during the scroll, often ending with the element hidden by the header. This commit fixes these issues by using the builder `scrollTo` util, which takes the header into account and only scrolls what needs to be. This function should always be preferred when scrolling in the builder. task-6314322 Forward-Port-Of: odoo/odoo#279201 Forward-Port-Of: odoo/odoo#275686
14 changes
Resolved issues and error corrections
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
In this commit: - When only one preset remains available after filtering table identifier in self-order mode, automatically select it and skip the preset selection page. - This avoids showing a location selection page when there is no actual choice available to the customer. Task:6217791 Enterprise PR : https://github.com/odoo/enterprise/pull/122979 Forward-Port-Of: odoo/odoo#280579 Forward-Port-Of: odoo/odoo#274301
Original PR description
In this commit: - When only one preset remains available after filtering table identifier in self-order mode, automatically select it and skip the preset selection page. - This avoids showing a location selection page when there is no actual choice available to the customer. Task:6217791 Enterprise PR : https://github.com/odoo/enterprise/pull/122979 Forward-Port-Of: odoo/odoo#280579 Forward-Port-Of: odoo/odoo#274301
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/file
Original PR description
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/files/formulaires/3310-ca3-sd/2026/3310-ca3-sd_5426.pdf ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: E5 and F3) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, E5 and F3 lines are empty opw-6357703 Forward-Port-Of: odoo/odoo#278635
## Steps to reproduce: ## Why the fix: opw-6428369
Original PR description
## Steps to reproduce: ## Why the fix: opw-6428369
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Original PR description
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Currently, l10n_vn_edi_unit_price and unit_price have the same label, triggering a warning. This commit changes the field name of l10n_vn_edi_price_unit to avoid the conflict. Backport of https://github.com/odoo/odoo/pull/260550 task-260550
Original PR description
Currently, l10n_vn_edi_unit_price and unit_price have the same label, triggering a warning. This commit changes the field name of l10n_vn_edi_price_unit to avoid the conflict. Backport of https://github.com/odoo/odoo/pull/260550 task-260550
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order
Original PR description
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order reference is currently sent only in the `Description` field which is for internal information and is not shown to customers on their bank statements. Customers only see "MACKNET", so they cannot identify which order the payment relates to. **Expected behavior:** - Should also send the order reference to Stripe's `statement_descriptor` field, which is the field used for the customer-facing bank statement reference. - The `statement_descriptor` value must comply with Stripe's requirements: Must not contain <, >, \, ', ", or * Must contain at least one letter Maximum 22 characters **Fix:** - Pass the order reference, which should already satisfy the first two requirements based on Odoo order/invoice naming conventions opw-6424994 Forward-Port-Of: odoo/odoo#280985
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here wh
Original PR description
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save…
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here when user set `Company name` on address it try to create parent company and again do vat validation and it raise validation error because `ID Type` on customer is not propagated to parent when creating parent company from portal. Fix: - Skip vat validation on parent company creation from address. To-do: We also need to pass `ID type` and other accounting related values when creating parent company from customer or make them dependent like `Vat`. Issued PR: https://github.com/odoo/odoo/pull/264356 opw-6434127 Forward-Port-Of: odoo/odoo#280859
- Some clients does not know that they can skip the feedback screen timeout by clicking on the screen. So we decrease the timeout to 1.5 seconds to avoid that they wait too much time. - This timeout was already reduced in version `saas-19.1` to 1 second (see PR: github.com/odoo/odoo/issues/235316) - We now set it to 1.5 seconds (because 1 second is not enough for the paid animation to finish on the feedback screen). task-id: 6425204 --- I confirm I have signed the CLA and read the PR gu
Original PR description
- Some clients does not know that they can skip the feedback screen timeout by clicking on the screen. So we decrease the timeout to 1.5 seconds to avoid that they wait too much time. - This timeout was already reduced in version `saas-19.1` to 1 second (see PR: github.com/odoo/odoo/issues/235316) - We now set it to 1.5 seconds (because 1 second is not enough for the paid animation to finish on the feedback screen). task-id: 6425204 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279444 Forward-Port-Of: odoo/odoo#278841
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creatin
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#275653
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Original PR description
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 tas
Original PR description
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 task-5411766 Forward-Port-Of: odoo/odoo#281384 Forward-Port-Of: odoo/odoo#272068
17 changes
Resolved issues and error corrections
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414
Original PR description
After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource
Original PR description
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the…
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource Calendar on the company (this is required and must differ from the employee's flexible working schedule). - Attempt to create a Time Off request for the employee. **Cause:** https://github.com/odoo/odoo/blob/5e865aeec854ca012dc5537f36b2e626ee39cf0b/addons/l10n_fr_hr_holidays/models/hr_leave.py#L17-L27 `_l10n_fr_leave_applies()` considers an empty employee calendar different from the company calendar. This sends flexible leaves to `_get_fr_date_from_to()`, which requires attendance rows and rejects the request. **Solution:** We need to require a concrete employee calendar before applying the French part-time calendar adjustment, leaving flexible employees to the core flexible-duration computation. opw-6417220 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
How to reproduce: - In a Fiscal Position, map the Downpayment account set in the settings to anything else - Put that Fiscal Position on a SO. - On that SO, create a Downpayment invoice -> The regular Downpayment account is used on the Downpayment invoice, but it should have been mapped because of the Fiscal Position account mapping Solution: Pre-map the company's default down payment account using the Sales Order's Fiscal Position before passing it to the invoice line creation
Original PR description
How to reproduce: - In a Fiscal Position, map the Downpayment account set in the settings to anything else - Put that Fiscal Position on a SO. - On that SO, create a Downpayment invoice -> The regular Downpayment account is used on the Downpayment invoice, but it should have been mapped because of the Fiscal Position account mapping Solution: Pre-map the company's default down payment account using the Sales Order's Fiscal Position before passing it to the invoice line creation. This ensures the correct account mapping is always respected for advance payment invoices. Task-6212218 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279464
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Original PR description
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Steps to reproduce: - Enable presets and set a preset carrying a tax-replacing fiscal position (e.g. "Takeout") as the default preset of the POS config - Take an order with another preset that has no fiscal position (e.g. "Dine In") - Refund that order from the ticket screen Issue: The refund is taxed with the fiscal position of the default preset instead of the one of the refunded order. The ticket screen displays the refund lines with the taxes of the original order, but the refund that
Original PR description
Steps to reproduce: - Enable presets and set a preset carrying a tax-replacing fiscal position (e.g. "Takeout") as the default preset of the POS config - Take an order with another preset that has no…
Steps to reproduce: - Enable presets and set a preset carrying a tax-replacing fiscal position (e.g. "Takeout") as the default preset of the POS config - Take an order with another preset that has no fiscal position (e.g. "Dine In") - Refund that order from the ticket screen Issue: The refund is taxed with the fiscal position of the default preset instead of the one of the refunded order. The ticket screen displays the refund lines with the taxes of the original order, but the refund that is actually created maps them through the wrong fiscal position. With tax-included prices the totals still match on screen, so the operator only sees the discrepancy after going back. Cause: The destination order of a refund is an empty order, created with the default preset and therefore with that preset's fiscal position. In TicketScreen.onDoRefund, the fiscal position of the refunded order was only copied onto it when the refunded order had one, so an order taken without a fiscal position kept the default preset's one. When an already existing empty order is reused as destination, whatever fiscal position was last set on it survives for the same reason. Fix: Always assign the fiscal position of the refunded order to the destination order, an empty one included, so a refund is taxed exactly like the order it refunds instead of silently switching. The preset itself is left untouched: it drives the ordering workflow (timing slot, customer identification) which must not be imposed on a refund. opw-6442664 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280672
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model
Original PR description
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three…
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model only grants read access to account.group_account_invoice and account.group_account_readonly. Steps to reproduce: - install `l10n_es_edi_verifactu` - create a salesman user with sales rights but no accounting right (*Own Documents Only* is enough) - create an ES company and an ES customer - give the salesman access to the ES company - activate Peppol in the general settings - log in as the salesman - create a sale order in the ES company for the ES customer - confirm it - click **Create Invoice** - click **Create Draft** Current behavior before PR: An error access is raised: Failed to read field account.move.l10n_es_edi_verifactu_document_ids You are not allowed to access 'Veri*Factu Document' (l10n_es_edi_verifactu.document) records. This operation is allowed for the following groups: - Invoicing/Billing - Technical/Show Accounting Features - Readonly Contact your administrator to request access if necessary. In Odoo sh (for databases 19.0), the standard test sale_management / TestSaleFlowTourPostInstall.test_basic_sale_flow_with_minimal_access_rights fails for the same reason as soon as l10n_es_edi_verifactu is installed alongside sale_management. Desired behavior after PR is merged: On a database with l10n_es_edi_verifactu installed, a non-accountant user having the possibility to create invoices should not have the error message displayed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280879
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order
Original PR description
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order reference is currently sent only in the `Description` field which is for internal information and is not shown to customers on their bank statements. Customers only see "MACKNET", so they cannot identify which order the payment relates to. **Expected behavior:** - Should also send the order reference to Stripe's `statement_descriptor` field, which is the field used for the customer-facing bank statement reference. - The `statement_descriptor` value must comply with Stripe's requirements: Must not contain <, >, \, ', ", or * Must contain at least one letter Maximum 22 characters **Fix:** - Pass the order reference, which should already satisfy the first two requirements based on Odoo order/invoice naming conventions opw-6424994 Forward-Port-Of: odoo/odoo#280985
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
Original PR description
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here wh
Original PR description
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save…
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here when user set `Company name` on address it try to create parent company and again do vat validation and it raise validation error because `ID Type` on customer is not propagated to parent when creating parent company from portal. Fix: - Skip vat validation on parent company creation from address. To-do: We also need to pass `ID type` and other accounting related values when creating parent company from customer or make them dependent like `Vat`. Issued PR: https://github.com/odoo/odoo/pull/264356 opw-6434127 Forward-Port-Of: odoo/odoo#280859
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 tas
Original PR description
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 task-5411766 Forward-Port-Of: odoo/odoo#280954 Forward-Port-Of: odoo/odoo#272068
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/file
Original PR description
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/files/formulaires/3310-ca3-sd/2026/3310-ca3-sd_5426.pdf ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: E5 and F3) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, E5 and F3 lines are empty opw-6357703 Forward-Port-Of: odoo/odoo#278635
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creatin
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#275653
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Original PR description
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
**Steps to reproduce:** - Go to Discuss app - Open a discussion - Add a reaction to one of the older messages - Create a new poll - Click on the vote number count - Close the vote dialog - Go back to the message that has the reaction - Open the reaction dialog for that message - Dialog opens, but the focus scroll down to the poll (also possible to reproduce with any visible active element, e.g. links or messages being edited) **Issue:** `Dropdown.closePopover()` re-focus the elemen
Original PR description
**Steps to reproduce:** - Go to Discuss app - Open a discussion - Add a reaction to one of the older messages - Create a new poll - Click on the vote number count - Close the vote dialog - Go back to the message that has the reaction - Open the reaction dialog for that message - Dialog opens, but the focus scroll down to the poll (also possible to reproduce with any visible active element, e.g. links or messages being edited) **Issue:** `Dropdown.closePopover()` re-focus the element that was active when the `MessageReactionList` dropdown was opened and `focus()` call doesn't use `preventScroll` so it moves back to `_focusedElBeforeOpen`. **Fix:** Use `focusToggleOnClosed` to prevent this behavior. opw-6355999
15 changes
Resolved issues and error corrections
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/file
Original PR description
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/files/formulaires/3310-ca3-sd/2026/3310-ca3-sd_5426.pdf ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: E5 and F3) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, E5 and F3 lines are empty opw-6357703 Forward-Port-Of: odoo/odoo#278635
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Original PR description
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created User as a Team Member 4. Create a Template Project as follows: * Add one task to the template project * Add the created Project role to the Task 5. Create a Service Type Product with: * Create on order: Project * Project Template: Created Template 6. Archive the Created User
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users
`(role.user_ids)` within the core task-copying logic in both `project` and
`project_enterprise` modules. This ensures archived users are universally
excluded from task assignments during template copying, regardless of what
triggers the template instantiation.
Related Enterprise PR: https://github.com/odoo/enterprise/pull/125637
opw-6350841In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model
Original PR description
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three…
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model only grants read access to account.group_account_invoice and account.group_account_readonly. Steps to reproduce: - install `l10n_es_edi_verifactu` - create a salesman user with sales rights but no accounting right (*Own Documents Only* is enough) - create an ES company and an ES customer - give the salesman access to the ES company - activate Peppol in the general settings - log in as the salesman - create a sale order in the ES company for the ES customer - confirm it - click **Create Invoice** - click **Create Draft** Current behavior before PR: An error access is raised: Failed to read field account.move.l10n_es_edi_verifactu_document_ids You are not allowed to access 'Veri*Factu Document' (l10n_es_edi_verifactu.document) records. This operation is allowed for the following groups: - Invoicing/Billing - Technical/Show Accounting Features - Readonly Contact your administrator to request access if necessary. In Odoo sh (for databases 19.0), the standard test sale_management / TestSaleFlowTourPostInstall.test_basic_sale_flow_with_minimal_access_rights fails for the same reason as soon as l10n_es_edi_verifactu is installed alongside sale_management. Desired behavior after PR is merged: On a database with l10n_es_edi_verifactu installed, a non-accountant user having the possibility to create invoices should not have the error message displayed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280879
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
Original PR description
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order
Original PR description
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order reference is currently sent only in the `Description` field which is for internal information and is not shown to customers on their bank statements. Customers only see "MACKNET", so they cannot identify which order the payment relates to. **Expected behavior:** - Should also send the order reference to Stripe's `statement_descriptor` field, which is the field used for the customer-facing bank statement reference. - The `statement_descriptor` value must comply with Stripe's requirements: Must not contain <, >, \, ', ", or * Must contain at least one letter Maximum 22 characters **Fix:** - Pass the order reference, which should already satisfy the first two requirements based on Odoo order/invoice naming conventions opw-6424994 Forward-Port-Of: odoo/odoo#280985
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80` ActivityController uses `useModel` which passes the raw `component.props` to `model.load()`, including the limit from `ir.actions.act_window` (default 80). This value ended up in `fetchActivityData` via `params.limit || this.initialLimit`, overriding `ActivityModel.DEFAULT_LIMIT` (100). The records li
Original PR description
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80`…
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80` ActivityController uses `useModel` which passes the raw `component.props` to `model.load()`, including the limit from `ir.actions.act_window` (default 80). This value ended up in `fetchActivityData` via `params.limit || this.initialLimit`, overriding `ActivityModel.DEFAULT_LIMIT` (100). The records list was not affected because `RelationalModel._getNextConfig` never reads `params.limit` (limit is not a `SEARCH_KEY`), so it always loaded 100 records correctly. But `fetchActivityData` used 80, causing a mismatch between the records shown and the activity counts in the column headers. ```js export const SEARCH_KEYS = ["comparison", "context", "domain", "groupBy", "orderBy"]; ``` The fix strips `params.limit` in `ActivityModel.load()` before passing params to `fetchActivityData`, so it falls back to `this.initialLimit (100)`. The pager `onUpdate` handler calls `fetchActivityData` directly with its own `params.limit` and is not affected. However, `ActivityController` never forwards `limit` to the model. This is why we always have `ActivityModel.DEFAULT_LIMIT (100)` without taking into account actions's limit. To fix this we have to add the limit via `this.props.limit`, as `ListController`. `useModelWithSampleData` already had the correct behavior by calling `model.load(getSearchParams(props))` which filters out non-search params like limit. In 19.0 useModel was updated to do the same, so the issue does not exist there. Link to 19.0 fix: https://github.com/odoo/odoo/pull/211697 opw-6281125 Forward-Port-Of: odoo/odoo#280747 Forward-Port-Of: odoo/odoo#273929
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resour
Original PR description
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe…
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L735-L749 so it will get the default value which is 10 so when calling onchange for the attendance_ids_1st_week and attendance_ids_2nd_week each attendance will be set to the odd_week_seq https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L184-L200 which will then make this condition fail https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 Second part was related to the `two_weeks_calendar` when saving, its value won't be passed to the vals_list in `web_save()` as when we read the values to be changed we ignore readonly fields and since two_weeks_calendar was used in invisible condition but isn't defined in a separate `<field>` the view create a tag for it ` <field name='two_weeks_calendar' invisible='True' readonly='True' data-used-by='invisible='flexible_hours or not two_weeks_calendar' (page,working_hours)' on_change='1'/> ` This tag would be readonly by default so when the ArchParser gets each field's info it puts `two_weeks_calendar` as a readonly field and ignore it in the creation values https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/web/static/src/views/fields/field.js#L276-L279 which then fails this condition and pass all the 2 weeks attendances in the else condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L134-L138 After fixing this another bug was found where if you saved the calendar the attendances will disappear. This was happening when we create the resource.calendar.attendance records it will call the inverse method of the attendance_ids_1st_week and attendance_ids_2nd_week where they are still not computed so it will set attendance_ids to empty https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L152-L156 so after when computing the two weeks attendance it will be empty as well and it will disappear. Last bug was if after creating this you tried to switch the calendar type it will call the same validation error mentioned earlier. As when calling _get_default_attendance_ids it will try to create attendances from the company's default working schedule which will have a conflict since the company's schedule is 2-weeks schedule and we are switching our schedule to 1-week schedule so we are gonna have attendances for 2-weeks in 1-week schedule so it will fail the same condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 ## Fix: To fix those issues we needed to set the sequence values when copying the data of the company's schedule when computing the default values. Also we need to skip the inverse method when we are still upon creating the records and to do so we are passing a context in the create method to skip the inverse. Last we need to check for the difference between the schedule type and the company's schedule when fetching the default attendances. opw-6374237 Forward-Port-Of: odoo/odoo#279182
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creatin
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#275653
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Original PR description
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/b
Original PR description
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not…
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/chatter/web/chatter_patch.js#L106-L138 Since the composer of the message in edition has no dropzone, a file dropped on it is caught by the chatter dropzone and ends up attached to the record instead of the message. Fix: Pass the message body as dropzoneRef to the composer in message.xml. The composer then creates its own dropzone over the message, the same way the chatter composer gets one from chatter.xml, and the dropped file is added to the message in edition. The chatter dropzone and the thread composer dropzone cover that same area and would show at the same time, so both are turned off while a message is in edition. The thread already knows which message that is through messageInEdition, so neither of them has anything to keep track of. Steps to reproduce: 1. Open the Contacts app and open any contact 2. Click Log note, type some text and click Log 3. Hover the note and click the pencil icon to edit it 4. Drag a file from the file explorer and drop it on the note => the file is added to the attachments of the contact instead of the note Ticket [link](https://www.odoo.com/odoo/project.task/6385377) opw-6385377 Forward-Port-Of: odoo/odoo#278373
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs: Failed to find 1 of "span" with text "This livechat conversation has ended." (Timeout of 10 seconds). Found 0 instead. This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of t
Original PR description
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs:
Failed to find 1 of "span" with text "This livechat conversation
has ended." (Timeout of 10 seconds). Found 0 instead.
This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of the visitor leaving, so the date goes back to `false` and the conversation still looks open.
One solution could have been to use `waitStoreFetch`, but its step comes from that same callback, and the helper returns six microtasks before the answer is inserted, on a hundred runs out of a hundred.
This commit fixes the issue by waiting for the messaging menu to list a plain channel, which arrives with the `channels_as_member` answer only.
https://runbot.odoo.com/odoo/error/94567213 changes
Resolved issues and error corrections
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more mo
Original PR description
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more modules. ZXing's BrowserQRCodeSvgWriter draws each module at a whole number of pixels of the canvas it is given (multiple = floor(canvas / (modules + 8))), so asking it for a fixed 150x150 or 200x200 canvas leaves a leftover margin that varies with the module count. The code shrinks as soon as the module count crosses a multiple of the canvas size. opw-6399878 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280000
The `qr_code` field on res.config.settings was labeled "Display SEPA QR-code", even though the underlying feature generates QR codes for any supported country scheme, not just SEPA. Align the label with the already-generic string used on res.company and the setting's help text. opw-6452422 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
The `qr_code` field on res.config.settings was labeled "Display SEPA QR-code", even though the underlying feature generates QR codes for any supported country scheme, not just SEPA. Align the label with the already-generic string used on res.company and the setting's help text. opw-6452422 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model
Original PR description
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three…
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model only grants read access to account.group_account_invoice and account.group_account_readonly. Steps to reproduce: - install `l10n_es_edi_verifactu` - create a salesman user with sales rights but no accounting right (*Own Documents Only* is enough) - create an ES company and an ES customer - give the salesman access to the ES company - activate Peppol in the general settings - log in as the salesman - create a sale order in the ES company for the ES customer - confirm it - click **Create Invoice** - click **Create Draft** Current behavior before PR: An error access is raised: Failed to read field account.move.l10n_es_edi_verifactu_document_ids You are not allowed to access 'Veri*Factu Document' (l10n_es_edi_verifactu.document) records. This operation is allowed for the following groups: - Invoicing/Billing - Technical/Show Accounting Features - Readonly Contact your administrator to request access if necessary. In Odoo sh (for databases 19.0), the standard test sale_management / TestSaleFlowTourPostInstall.test_basic_sale_flow_with_minimal_access_rights fails for the same reason as soon as l10n_es_edi_verifactu is installed alongside sale_management. Desired behavior after PR is merged: On a database with l10n_es_edi_verifactu installed, a non-accountant user having the possibility to create invoices should not have the error message displayed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280879
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037**Steps to reproduce:** This issue is hard to reproduce because it requires a live ZATCA connection: - As a user with read-only permission on journals, send an invoice to ZATCA. - You get an access error on the journal, and the invoice is unchanged (You can try sending it again to ZATCA). **Issue:** What happens is: - A user with read-only permission on journals sends an invoice to ZATCA. - If ZATCA responds with a 200 (successfully submitted), we try to write on the field `journal.l10n
Original PR description
**Steps to reproduce:** This issue is hard to reproduce because it requires a live ZATCA connection: - As a user with read-only permission on journals, send an invoice to ZATCA. - You get an access error on the journal, and the invoice is unchanged (You can try sending it again to ZATCA). **Issue:** What happens is: - A user with read-only permission on journals sends an invoice to ZATCA. - If ZATCA responds with a 200 (successfully submitted), we try to write on the field `journal.l10n_sa_latest_submission_hash` - With no write permissions, the write fails and all changes are rolled back (on odoo, not on ZATCA) - We can send the invoice again to ZATCA, resulting in duplicates. **Solution:** - Added a sudo when writing on the field: `journal.l10n_sa_latest_submission_hash` opw-6320179 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278728
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8
Original PR description
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1)…
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8. *Create Invoice* again, with a **Timesheets Period of 01/06 → 31/07** ### Current behavior The invoice bills **9 h**: the 4.5 h that were invoiced and not credited are billed a second time. ### Expected behavior The invoice bills **4.5 h** — the quantity delivered minus the quantity invoiced. ### Cause of the issue Posting a partial credit note clears `timesheet_invoice_id` on every timesheet the reversed invoice had linked (`sale_timesheet/models/account_move.py`, `action_post`), because a credit note carries a quantity and never a set of timesheets, so there is no way to tell which hours it credited. All of those hours therefore become candidates again in `_recompute_qty_to_invoice`, which assigns their sum to `qty_to_invoice` without comparing it to what is still due on the line. ### Fix Timesheet links cannot express a partially invoiced timesheet, so they are used only to select the hours a period concerns, while the quantity that may still be billed is `qty_delivered - qty_invoiced`. The period lookup is capped by that remainder, and kept at zero or above so that an over-invoiced line is corrected by a deliberate credit note rather than as a side effect of invoicing a period. ### Tests Five tests are added to `addons/sale_timesheet/tests/test_sale_timesheet.py`. Three of them fail without the fix: | test | without the fix | | --- | --- | | `test_period_invoice_does_not_rebill_refunded_invoice_hours` | `9.0 != 4.5` | | `test_period_invoice_after_refund_is_computed_per_line` | `4.0 != 1.5` | | `test_period_invoice_after_refund_of_an_over_invoiced_line` | `8.0 != 1.0` | The other two cover behaviour that is not exercised today and that the fix must not break: an over-invoiced line (which must be left out rather than credited, and must not prevent the other lines of the order from being invoiced) and the reversed invoice's own `invoice_date`, which must not influence the quantity billed for a period. The full `sale_timesheet` suite passes (86 tests). Forward-Port-Of: odoo/odoo#280721 Forward-Port-Of: odoo/odoo#280536
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog appears and then Press `'ESC'`. 3. Chat window closes whereas the dialog should have closed. Since #169737, pressing 'esc' on the seen-by dialog closes the chat window instead of the dialog. The chat window's root element has a keydown handler that closes the window on `'escape'`, and cat
Original PR description
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog…
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog appears and then Press `'ESC'`. 3. Chat window closes whereas the dialog should have closed. Since #169737, pressing 'esc' on the seen-by dialog closes the chat window instead of the dialog. The chat window's root element has a keydown handler that closes the window on `'escape'`, and catches focus by default whenever something non-focusable is clicked inside it (e.g. the seen-by indicator). The seen-by dialog's content had no focusable element, so it never grabbed focus for itself, leaving focus on the chat window. Pressing 'escape' therefore closed the chat window instead of the dialog. This commit fixes the issue by adding tabindex on the template, letting the dialog grab focus like other dialogs/popovers already do, so `'escape'` is handled by the dialog first. task-4895004 Forward-Port-Of: odoo/odoo#278847
The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
## Steps to Reproduce: - Install the Time Off module. - Create an Accrual Plan without any milestones. - Create an Accrual Allocation using the newly created accrual plan. - Approve the allocation. - Add a milestone to the accrual plan. - Create a new Time Off request after the allocation start date. - Save the record. ## Error: `TypeError - '>' not supported between instances of 'datetime.date' and 'bool'` ## Cause: `lastcall` is initialized by method `_add_lastcalls()`, which is
Original PR description
## Steps to Reproduce: - Install the Time Off module. - Create an Accrual Plan without any milestones. - Create an Accrual Allocation using the newly created accrual plan. - Approve the allocation. -…
## Steps to Reproduce: - Install the Time Off module. - Create an Accrual Plan without any milestones. - Create an Accrual Allocation using the newly created accrual plan. - Approve the allocation. - Add a milestone to the accrual plan. - Create a new Time Off request after the allocation start date. - Save the record. ## Error: `TypeError - '>' not supported between instances of 'datetime.date' and 'bool'` ## Cause: `lastcall` is initialized by method `_add_lastcalls()`, which is only called at create and write. When an accrual allocation is created with an accrual plan that has no milestones, `_add_lastcalls()` returns early because `level_ids` is empty, leaving `lastcall` set to `False`. - [1] If a milestone is added later, `lastcall` is compared with `first_level_start_date`, resulting in a comparison between boolean and datetime, which raises an error. ## Fix: When `lastcall` is not set, default it to `first_level_start_date`. [1] - https://github.com/odoo/odoo/blob/27036bea232572ba692fbb95387911eb453266bf/addons/hr_holidays/models/hr_leave_allocation.py#L703-L706 sentry-7615375197 Forward-Port-Of: odoo/odoo#280674
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test: ``` show banner for new message after thread was read from another device Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))" (Timeout of 10 seconds). Found 0 instead. ``` This happens because a message received while the composer h
Original PR description
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test:
```
show banner for new message after thread was read from another device
Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))"
(Timeout of 10 seconds). Found 0 instead.
```
This happens because a message received while the composer has the focus is marked as read whatever the scroll position, while the counter the banner reads is frozen only when the conversation is scrolled to the bottom too. The counter therefore goes up for a scrolled up user, and back to zero as soon as the read reaches the server.
This commit marks a received message as read only when the conversation is scrolled to the bottom, as the other automatic reads already do.
https://runbot.odoo.com/odoo/error/945671When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins 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#281269 Forward-Port-Of:
Original PR description
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins 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#281269 Forward-Port-Of: odoo/odoo#277818
6 changes
Resolved issues and error corrections
This fix makes cash basis report tests use the configured outstanding receipts account instead of assuming a fixed account code. It helps prevent false test failures when account codes differ between database setups, improving reliability without changing business functionality.
Original PR description
Description of the issue this commit addresses: Commit 63f5646cfd75 made the tests use the default outstanding account but hard-coded code 101403. In an all-module database, generated account codes depend on existing accounts, so Outstanding Receipts may use code 101404 and make otherwise correct report assertions fail. --- Desired behavior after this commit is merged: This commit derives the expected report line name from the configured outstanding receipts account, making the assertions independent of its generated code. --- runbot-[231581](https://runbot.odoo.com/odoo/error/231581) Forward-Port-Of: odoo/enterprise#126743 Forward-Port-Of: odoo/enterprise#125652
This update improves how the Belgian payroll module calculates DMFA reported days, especially for employees working 40-hour weeks. It helps prevent overstated day totals in payroll declarations, improving reporting accuracy and reducing correction work.
Original PR description
Currently, there is problem with DMFA Number of days Computation, If we have case where the employee working hour is 40h/week, the calculations mentioned in report 67.5 days, which is too many, In this PR, expected to update the number of days on DMFA computations task-6432418
The tax return view now adjusts its status bar layout to match the number of states shown. This prevents broken or misaligned cards for country-specific tax returns, such as Indian reports with four states.
Original PR description
…te counts Steps to reproduce: - Install l10n_in_reports and select an Indian company - Go to the tax return and set a date in the past --> The state bar layout breaks because there are 4 states, but the CSS grid was previously hardcoded to a maximum of 3 columns. Cause: The CSS `--columns` rule assumed a maximum of 3 states across return cards. When 4 states are present, the grid columns shift or break. Fix: Calculate the maximum state count across all visible records in the kanban renderer (`maxStateCount`) and set it as a CSS variable on the parent container. This ensures all cards in the view align consistently to the maximum number of states present without hardcoding column counts.
The Point of Sale appointment booking Gantt view now loads capacity information when it first opens. This prevents attendee labels from showing confusing placeholder text like "undefinedp" and makes booking details clearer for staff.
Original PR description
Steps to reproduce : - Open PoS and navigate to the Booking view (Gantt View). - Create a booking or view existing bookings / time-off leaves on the Gantt chart. - Observe 'undefinedp' appended to attendee names on Gantt pills (e.g. 'Billy Fox undefinedp'). Issue : 'undefinedp' is displayed on Gantt view pills instead of the correct capacity. Cause : Capacity information was not being fetched during the initial Gantt view rendering. Fix : Ensured capacity data is fetched during initial Gantt view loading so guest capacity displays properly on Gantt pills. Task ID: 6405279
This fixes an issue in the Timesheet timer form where clicking Save or Reset could trigger an error instead of completing the action. The change helps users record or adjust time entries without interruption.
Original PR description
469a7d200ce ([FIX] timesheet_grid: focus on description input, odoo/enterprise#125993) was forward-ported from saas-19.4 onto master a day after 6d3c12624e4 had turned `descriptionFieldRef` into a `signal.ref()`, which has no `.el`: clicking Save or Reset in the timesheet timer form throws on `undefined.querySelector` in onPatched -- the very refocus the original fix was adding. The read is correct on the back branches, where the ref is still a `useRef()`; call the ref on master.
Website Studio now ignores automatic cleanup edits when deciding whether a user has made changes. This helps prevent the system from treating background formatting updates as user edits, reducing false change prompts or unnecessary save behavior.
Original PR description
Automatic mutations done by `normalize` are now marked with `isAutomatic`. This commit ignore those in `on_pending_mutations_staged_handlers`.
10 changes
Resolved issues and error corrections
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Before this commit, duplicating several projects at once from the list view gave every copy the milestones of all the duplicated projects, because the copy loop assigned the milestones of the whole recordset instead of the ones of the project being copied. Duplicating a single project behaves correctly, which hid the issue. Steps to reproduce: - create two projects with milestones enabled, add a milestone to the first one and two others to the second one - select both projects in the list v
Original PR description
Before this commit, duplicating several projects at once from the list view gave every copy the milestones of all the duplicated projects, because the copy loop assigned the milestones of the whole recordset instead of the ones of the project being copied. Duplicating a single project behaves correctly, which hid the issue. Steps to reproduce: - create two projects with milestones enabled, add a milestone to the first one and two others to the second one - select both projects in the list view and duplicate them Each copy contains the three milestones instead of only the milestones of its original project. Solution: Copy the milestones of the project being duplicated. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls _generate_pos_order_invoice as the acting user, with no sudo anywhere on the way. So on a Vietnamese POS with auto-send to SInvoice enabled, a user in point_of_sale.group_pos_user alone hit Access Denied by ACLs for operation: read, model: pos.config, fields: l10n_vn_pos_symbol and the order nev
Original PR description
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls…
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls _generate_pos_order_invoice as the acting user, with no sudo anywhere on the way. So on a Vietnamese POS with auto-send to SInvoice enabled, a user in point_of_sale.group_pos_user alone hit
Access Denied by ACLs for operation: read, model: pos.config, fields: l10n_vn_pos_symbol
and the order never finished syncing - the receipt screen's Done button stayed disabled and the checkout dead-ended.
This is reachable from the module's own test suite, which is what makes it more than theoretical: point_of_sale's start_pos_tour logs in as `pos_user` (group_pos_user, NOT group_pos_manager - that is `pos_admin`), so test_l10n_vn_edi_pos_refund_reason_tour exercises exactly the unprivileged path.
Reading the config as sudo is the right resolution rather than widening the field's groups: the salesperson is never shown the symbol or allowed to change it, it is only stamped onto the invoice their own sale produces, which is what a per-POS configuration field is for. Both symbols are read through the same sudo recordset so the company-level fallback keeps working identically.
Reproduced and verified on v18_full (5-repo addons path):
before - FAILED: [13/36] Tour L10nVnEdiPosRefundReasonTour -> "go to next screen from
receipt"; 1 failed, 0 error(s) of 1 tests
after - tour succeeded for both tours in the class; 0 failed, 0 error(s) of 2 tests,
and no ACL line left in the log
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prSteps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create a service product: - Invoicing policy = Based on Delivered Quantity - Track service =Timesheets on tasks - Create and confirm a sale order for quantity 1 - Log 20h on the task. Create Invoice → 20.00. Then, post - On the invoice: Reverse → Partial Refund, set the credit-note quantity to 11.00 - Post credit note → qty_invoiced = 9.00 - Log 5h. Create Invoice → 16.00. Post. (this part was already fixed, see
Original PR description
### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create a service product: - Invoicing policy = Based on Delivered Quantity - Track service =Timesheets on tasks - Create and confirm…
### Steps to reproduce:
- Download 'Sales' and 'Timesheets' apps
- Create a service product:
- Invoicing policy = Based on Delivered Quantity
- Track service =Timesheets on tasks
- Create and confirm a sale order for quantity 1
- Log 20h on the task. Create Invoice → 20.00. Then, post
- On the invoice: Reverse → Partial Refund, set the credit-note quantity to 11.00
- Post credit note → qty_invoiced = 9.00
- Log 5h. Create Invoice → 16.00. Post. (this part was already fixed, see below)
- Log 3h. Create Invoice
> Expected: an invoice for 3.00h — qty_delivered (28) - qty_invoiced (25)
> Actual: a credit note (out_refund) for 6.00h
### Cause of Issue:
A previous [PR](https://github.com/odoo/odoo/pull/268025) fixed a related issue where `_recompute_qty_to_invoice` failed to account for hours already invoiced/refunded when a credit note had been posted against a prior invoice, causing already-invoiced hours to be re-invoiced.
However, that approach relies on invoice *lineage* (which invoice was reversed) rather than on the actual net amount already invoiced.
https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/sale_timesheet/models/sale_order_line.py#L183 This caused the already-resolved refund to be subtracted a second time (3-(20-11) = -6), producing a negative `qty_to_invoice` and, consequently, a credit note instead of an invoice for the newly logged hours.
### Fix:
Replace the lineage-based tracking with a simpler and more efficient way that holds across any number of refund/re-invoice cycles.
In case there are refund moves:
`qty_to_invoice = total_delivered_quantity − net_posted_invoiced_quantity`
`net_posted_invoiced_quantity` is computed directly from all **posted** invoice lines linked to the
SO line, without needing to determine which invoice a given credit note was reversing or whether
its timesheets have since moved to a newer invoice.
And in case of no refunds (less complex flow), we only include the relevant timesheets.
opw-6253650When modifying project_id on a timesheet through mass edit/rpc or anything that is not triggering `onChange`. The task_id would not be reset if it doesnt' belong to the new project set on the timesheet. Steps to reproduce: ------------------- * Install studio for easier reproducing of the issue * Open the timesheet list view * Open studio and activate the mass edit on the view * Modify the project_id on multiple records > Observation: The task_id stays the same even if they do not belon
Original PR description
When modifying project_id on a timesheet through mass edit/rpc or anything that is not triggering `onChange`. The task_id would not be reset if it doesnt' belong to the new project set on the timesheet. Steps to reproduce: ------------------- * Install studio for easier reproducing of the issue * Open the timesheet list view * Open studio and activate the mass edit on the view * Modify the project_id on multiple records > Observation: The task_id stays the same even if they do not belong to the new set project Why the fix: ------------ Instead of relying only on the onChange we add an inverse to the project_id that will reset the task when needed. opw-6259149
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear
Original PR description
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the…
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear from the original order line. Protect so_line during the write and drop the pending recompute: deleting an invoice must only make the hours invoiceable again, not change their allocation. Steps to reproduce: - Install Sales and Timesheets - Create a service product with invoice policy "Based on Timesheets" and "Create a task in a new project" - Create and confirm a sale order with this product - Log a timesheet on the generated task - Create the invoice (keep it in draft) - Remove the Sales Order Item from the task and from the project settings (or point them to a sale order item of another order) - Delete the draft invoice - Open the timesheet: its Sales Order Item is emptied (or replaced by the other order's item, whose delivered quantity now includes the hours sold on the original order), and the original line's delivered quantity is reset --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279552
Prerequisite: ------------------------------------- 1. Configure outgoing mail server Steps to reproduce: ------------------------------------- 1. Install Contact and Sales modules 2. Create a Company contact and it's child contact as follows: * Type: Invoice Address * Keep the Name field empty and add any email 3. Create and confirm the sale order with the Child Contact as customer 4. Send the order by Email 5. Click on the mail icon on the Mail in Chatter Observation:
Original PR description
Prerequisite: ------------------------------------- 1. Configure outgoing mail server Steps to reproduce: ------------------------------------- 1. Install Contact and Sales modules 2. Create a…
Prerequisite:
-------------------------------------
1. Configure outgoing mail server
Steps to reproduce:
-------------------------------------
1. Install Contact and Sales modules
2. Create a Company contact and it's child contact as follows:
* Type: Invoice Address
* Keep the Name field empty and add any email
3. Create and confirm the sale order with the Child Contact as customer
4. Send the order by Email
5. Click on the mail icon on the Mail in Chatter
Observation:
-------------------------------------
The recipient name is displayed as false in the notification popover.
Issue:
-------------------------------------
The bug traces through two separate layers
1. Child contacts of type invoice, delivery, etc. are allowed to have `name = False`. `_to_store()` serialized only the name field for recipients, which produced `{'name': false}` for nameless contacts.
2. The frontend used `name` with no fallback and rendered 'false' https://github.com/odoo/odoo/blob/0b17840fb3cc72935e1a6302a057fb55c253c498/addons/mail/static/src/core/common/message_notification_popover.xml#L8
Solution:
-------------------------------------
1. Include `display_name` in the recipient serialization, since it is always computed and never empty
2. Use `displayName` as a frontend fallback when name is missing.
3. Used `sudo` in a condition to respect the multicompany access rights
**Before:**
<img width="576" height="314" alt="image" src="https://github.com/user-attachments/assets/26c7e67d-9ab2-4089-bd07-2871c2039f8f" />
**After:**
<img width="630" height="317" alt="image" src="https://github.com/user-attachments/assets/7c84afef-48b3-4243-bf6e-3bac7198ccf6" />
opw-5898004The right value often comes from the user and the search implementation may not handle 'any' properly, however 'in' is nearly always implemented. For most cases, transform 'any' into a 'in' before calling Field.search. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280362
Original PR description
The right value often comes from the user and the search implementation may not handle 'any' properly, however 'in' is nearly always implemented. For most cases, transform 'any' into a 'in' before calling Field.search. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280362
### Steps to reproduce: - Go to Email Marketing > Mailing Lists > Mailing Lists - Open any mailing list and click the 'Recipients' smart button > Only the contacts belonging to that mailing list are shown, as expected - Refresh the page > All mailing contacts in the database are shown instead, filtered only by `('is_blacklisted', '=', False)`. Notice that the mailing list's id is still present in the URL, but is no longer reflected in the results ### Cause of Issue: The 'Recipien
Original PR description
### Steps to reproduce: - Go to Email Marketing > Mailing Lists > Mailing Lists - Open any mailing list and click the 'Recipients' smart button > Only the contacts belonging to that mailing list are…
### Steps to reproduce:
- Go to Email Marketing > Mailing Lists > Mailing Lists
- Open any mailing list and click the 'Recipients' smart button
> Only the contacts belonging to that mailing list are shown, as expected
- Refresh the page
> All mailing contacts in the database are shown instead, filtered only by
`('is_blacklisted', '=', False)`. Notice that the mailing list's id is still present in the URL, but is no longer reflected in the results
### Cause of Issue:
The 'Recipients' button called `action_view_contacts()`, which fetched the *generic* action also used by the 'Mailing List Contacts' menu (`mass_mailing.action_view_mass_mailing_contacts`) and patched its domain and context in memory before returning it: https://github.com/odoo/odoo/blob/76e005f57ffc5aca296d261a382b74ff95bd5990/addons/mass_mailing/models/mailing_list.py#L168-L172
This override only exists for the response triggered by the button click. The generic action's own `domain` field, stored in `ir.actions.act_window`, is empty and evaluates to [], while the `context` is `{'search_default_filter_not_email_bl': 1}`
https://github.com/odoo/odoo/blob/76e005f57ffc5aca296d261a382b74ff95bd5990/addons/mass_mailing/views/mailing_contact_views.xml#L165-L177 This filter has the domain `["is_blacklisted", "=", false]` https://github.com/odoo/odoo/blob/76e005f57ffc5aca296d261a382b74ff95bd5990/addons/mass_mailing/views/mailing_contact_views.xml#L23-L26
On refresh, the web client rebuilds the current action purely from the action id encoded in the URL. It re-reads the action definition straight from `ir.actions.act_window` and never re-invokes `action_view_contacts()`, so the in-memory domain override from the original click is lost and only the generic action's static domain remains.
### Fix:
Gave the 'Mailing List Contacts' menu its own dedicated action (`action_view_mailing_contacts_menu`)
and adjusted the old view to suit the 'Recepients' instead of reusing the generic one so that the
filter will live on the action record itself and will be evaluated server-side from `active_id` on
every load. Also, this way there won't be any traceback on existing DBs if they get restarted
without upgrading their xml actions, since all the changes are in .xml files.
opw-63855898 changes
Resolved issues and error corrections
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037#### Description of the issue: Activity filters using context_today() bucket against the UTC date instead of the user's local date, off by one for part of the day. Partial revert of #265250 (e048bb5), scoped to PyDate: UTC getters are right for PyDateTime, wrong for a calendar day. #### Current behavior before PR: A Perth (UTC+8) user finds an activity due today under "Future Activities" from 00:00 to 08:00 local, while the chatter labels the same activity "Today". #### Desired behavior
Original PR description
#### Description of the issue: Activity filters using context_today() bucket against the UTC date instead of the user's local date, off by one for part of the day. Partial revert of #265250 (e048bb5), scoped to PyDate: UTC getters are right for PyDateTime, wrong for a calendar day. #### Current behavior before PR: A Perth (UTC+8) user finds an activity due today under "Future Activities" from 00:00 to 08:00 local, while the chatter labels the same activity "Today". #### Desired behavior after PR is merged: context_today(), today and current_date return the user's local calendar day, so filters agree with the chatter. PyDateTime and PyTime keep the UTC getters; now and time.strftime() are unchanged. opw-6415985 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
An old refactor left some data around that are in conflict with other records for the same model. 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
Original PR description
An old refactor left some data around that are in conflict with other records for the same model. 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
The right value often comes from the user and the search implementation may not handle 'any' properly, however 'in' is nearly always implemented. For most cases, transform 'any' into a 'in' before calling Field.search. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
The right value often comes from the user and the search implementation may not handle 'any' properly, however 'in' is nearly always implemented. For most cases, transform 'any' into a 'in' before calling Field.search. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
l10n_fr_pdp's settings view inherits account_peppol and uses peppol_use_parent_company in `invisible`s. The node for that field is provided by account_peppol, but it was only added to account_peppol settings view in 0ab1e0323894. On a database whose account_peppol was not updated after this commit, installing l10n_fr_pdp does not upgrade account_peppol, so this invisible references a field that doesn't exist in the view, so tb at install ``` Error while validating view near: <form string=
Original PR description
l10n_fr_pdp's settings view inherits account_peppol and uses peppol_use_parent_company in `invisible`s. The node for that field is provided by account_peppol, but it was only added to account_peppol…
l10n_fr_pdp's settings view inherits account_peppol and uses peppol_use_parent_company in `invisible`s. The node for that field is provided by account_peppol, but it was only added to account_peppol settings view in 0ab1e0323894. On a database whose account_peppol was not updated after this commit, installing l10n_fr_pdp does not upgrade account_peppol, so this invisible references a field that doesn't exist in the view, so tb at install
```
Error while validating view near:
<form string="Settings" class="oe_form_configuration" js_class="base_settings">
<field name="is_root_company" invisible="1"/>
<app data-string="General Settings" string="General Settings" name="general_settings" logo="/base/static/description/settings.png">
Field 'peppol_use_parent_company' used in modifier 'invisible' (peppol_use_parent_company or account_peppol_proxy_state not in ('sender', 'pending', 'active')) must be present in view but is missing.
View error context:
{'file': '/home/odoo/src/odoo/17.0/addons/l10n_fr_pdp/views/res_config_settings_views.xml',
'line': 1,
'name': 'res.config.settings.view.form.inherit.proxy.user',
'view': ir.ui.view(2640,),
'view.model': 'res.config.settings',
'view.parent': ir.ui.view(1604,),
'xmlid': 'res_config_settings_view_form'}
```
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-prWe still have cases of people being confused by the fact that they send their invoices, reset it to draft, change something, then re-sending. Of course, the re-sending does not send on peppol, as it's already sent. It's more confusing than anything else. Prevent it if they're sent and not in error. task-6459869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
We still have cases of people being confused by the fact that they send their invoices, reset it to draft, change something, then re-sending. Of course, the re-sending does not send on peppol, as it's already sent. It's more confusing than anything else. Prevent it if they're sent and not in error. task-6459869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Description of the issue/feature this PR addresses: Odoo supports WebP image fields, but `base_import` validates remote images with `PIL.Image.open()`. Odoo intentionally leaves Pillow's WebP decoder unloaded, so a valid WebP URL is rejected as an unidentified image. Current behavior before PR: Importing a valid WebP image URL fails with `cannot identify image file`. Oversized and unsupported WebP files are also rejected by Pillow before the import-specific size policy can be applied. Desire
Original PR description
Description of the issue/feature this PR addresses: Odoo supports WebP image fields, but `base_import` validates remote images with `PIL.Image.open()`. Odoo intentionally leaves Pillow's WebP decoder unloaded, so a valid WebP URL is rejected as an unidentified image. Current behavior before PR: Importing a valid WebP image URL fails with `cannot identify image file`. Oversized and unsupported WebP files are also rejected by Pillow before the import-specific size policy can be applied. Desired behavior after PR is merged: Use Odoo's existing WebP header parser for dimension validation. Valid WebP URLs import unchanged, unsupported WebP remains rejected, and the existing 42-million-pixel import limit remains enforced. Tests cover valid, unsupported, and oversized WebP URL payloads. The complete `test_base_import` suite passes (56 tests, 0 failures/errors). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr