Daily updates from Odoo
Wednesday, August 19, 2026
285 changes
22 changes
Resolved issues and error corrections
This update corrects the display height of product descriptions in delivery forms, so edited text is no longer cut off or hidden. It improves the reliability of the picking screen and prevents users from missing important information when updating delivery details.
Original PR description
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on…
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on editing the description -> Observe that the description is partially hidden because the widget height is incorrectly computed **Cause** Since commit https://github.com/odoo/odoo/commit/e4f4171e1bc838840c0bd6111cd78f348b201ac2, `useProductAndLabelAutoresize` no longer assigns a height to the widget root. The corresponding widget is `MoveProductLabelField`, which extends `ProductNameAndDescriptionField`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/stock/static/src/views/picking_form/stock_move_product_label.js#L5 It uses `useProductAndLabelAutoresize`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/product/static/src/product_name_and_description/product_name_and_description.js#L54-L56 **Solution** Explicitly add a div around the product display and description to still use the `Autoresize` Forward-Port-Of: odoo/odoo#280056 Forward-Port-Of: odoo/odoo#271564
This change restores the expected description for a Point of Sale popup so automated tests can run without errors. It does not change the customer-facing behavior of the popup, but it prevents test failures that were blocking quality checks.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790This update fixes a problem that could block users from editing or unmerging merged accounts when the original accounts had no codes. It ensures empty values are stored correctly so account management works normally again.
Original PR description
Repro steps: 1) Create 2 accounts in 2 different companies, both with no code 2) Merge the 2 accounts 3) On the merged account, attempt to a) add a code b) unmerge the accounts Problems: a) psycopg2.errors.InvalidParameterValue: cannot call jsonb_each on a non-object b) cannot delete from scalar Root cause: json.dumps(code_by_company) returns 'null' when code_by_company is None. This results in code_store being stored as JSON null instead of SQL null resulting in the errors mentioned above because the field is expected to hold SQL NULL when empty instead of JSON null. task-6397515 Forward-Port-Of: odoo/odoo#277773
This change prevents the system from creating the same vendor bill more than once when messages are received from the external service. Previously, duplicate incoming messages could be processed again, which led to duplicate bills appearing in accounting.
Original PR description
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282042 Forward-Port-Of: odoo/odoo#274963
This change prevents an error that could stop a repair from being completed when it includes service lines and is covered under warranty. When the repair is under warranty, the related sales or invoice line is now set to zero, so the repair flow completes normally.
Original PR description
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice. Steps to replicate: - Install `repair` with demo. - Create a new repair…
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice.
Steps to replicate:
- Install `repair` with demo.
- Create a new repair order with a customer and check `Under Warranty`.
- Click on the `Services` page and add a product.
- Click on `Quote` button.
- Return to the repair order through breadcrumbs.
- Click `Confirm Repair` > `Start Repair` > `End Repair`.
Error:
```
File '/home/odoo/odoo19/community/addons/repair/models/repair_service_line.py', line 120, in _update_repair_sale_order_line
self.price_unit = 0.0
^^^^^^^^^^^^^^^
AttributeError: 'repair.service.line' object has no attribute 'price_unit'
```
Cause:
- The error was introduced after a recent improvement [PR].
- The `repair.service.line` model does not contain a `price_unit` field, which causes the error.
- The `price_unit` field is present in the related Sale Order Line or Invoice Line.
Solution:
- The price of the linked Sale Order Line or Invoice Line is now set to zero when the product is under warranty.
[PR]: https://github.com/odoo/odoo/pull/260278/files#diff-1ff5f0c96411a07c366ef6410fc4580798593205b57d5740fbb4a56259341c98R102
sentry-7620551626
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix ensures the payment card shown in the customer portal follows the same rules as the /my/payment_method page. As a result, customers will see a consistent set of payment options in both places, avoiding confusion when cards appear or disappear unexpectedly.
Original PR description
Commit bcfeed4b24f51 introduce `ResPartner._get_payment_tokens` method to determine which tokens are available for a specific partner, in case that method is overridden in some way, the portal card will not be visible/hidden correctly. This commit, use that method to align the portal card visibility with the tokens that will effectively be shown on the `/my/payment_method` page. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The hidden avatar counter in chat-related lists now adjusts correctly when the number reaches double digits, so labels like "+10" are no longer cut off. This makes the count easier to read and avoids confusion in views that use avatar tags, such as Live Chat.
Original PR description
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This…
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This causes the text to get cut off, making the exact number unreadable. Solution: This commit updates the badge container to properly accommodate larger numbers. The text now fits entirely within the badge without overflowing, ensuring the hidden tag count remains fully readable. Steps to reproduce (runbot v19.3): 1. Open the Live Chat app (or any view using the many2many_avatar_user widget). 2. Add enough agents to a session so the remaining count hits double digits (10 or more). 3. Observe that the badge showing the remaining agent count (e.g., "+10") overflows the badge container, cutting off the text and making it unreadable. opw-6453976 <img width="2655" height="1111" alt="avatar_tag_193_before" src="https://github.com/user-attachments/assets/9c31007d-5300-4bb7-a703-01a13b5bdd10" /> <img width="2655" height="1112" alt="avatar_tag_193_after" src="https://github.com/user-attachments/assets/7b2a4074-3738-4a6c-9649-f6652601f3f3" /> Forward-Port-Of: odoo/odoo#281570
This change makes an automated image upload test more reliable by giving the system a little more time to detect the uploaded image. It helps prevent occasional false failures in testing, especially when the server is under heavy load.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 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#281200
The live chat statistics section now uses the available screen width more effectively on mobile devices. This removes awkward empty space and makes the interface cleaner and easier to read on smaller screens.
Original PR description
Previously, the live chat statistics section did not use the available width on mobile devices, leaving unnecessary empty space and resulting in an awkward layout. This PR makes the statistics cards take the full available width on mobile, providing a cleaner and more consistent interface. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="372" height="805" alt="image" src="https://github.com/user-attachments/assets/6934927b-f744-4c93-b63e-1f49ecd33004" /> </td> <td> <img width="382" height="734" alt="image" src="https://github.com/user-attachments/assets/24f8b7e4-9fe7-4fa0-bf64-5d7917623830" /> </td> </tr> </table> --- Task ID - 6372787 Forward-Port-Of: odoo/odoo#274945
Currently an error occurs when user tries to send a pdf of a invoice to a customer. Steps to replicate: (Make sure to have `python 3.14.4` and `pypdf=5.4.0`) - Install `l10n_sa_edi` with demo and switch to `My Saudi Arabia Company`. - Open invoices and create an invoice with customer and an invoice line. - Click `Send` > Again Click `Send`. Error: ``` AttributeError: 'PageObject' object has no attribute 'getObject' AttributeError: No attribute getObject found in IndirectObject or poi
Original PR description
Currently an error occurs when user tries to send a pdf of a invoice to a customer. Steps to replicate: (Make sure to have `python 3.14.4` and `pypdf=5.4.0`) - Install `l10n_sa_edi` with demo and…
Currently an error occurs when user tries to send a pdf of a invoice to a customer. Steps to replicate: (Make sure to have `python 3.14.4` and `pypdf=5.4.0`) - Install `l10n_sa_edi` with demo and switch to `My Saudi Arabia Company`. - Open invoices and create an invoice with customer and an invoice line. - Click `Send` > Again Click `Send`. Error: ``` AttributeError: 'PageObject' object has no attribute 'getObject' AttributeError: No attribute getObject found in IndirectObject or pointed object ``` - A recent [PR] introduced the old `getObject()` API in the PDF/A conversion code, even though it has been renamed to `get_object()` in the modern pypdf API. - As PyPDF2 1.x compatibility has already been removed, `getObject()` is no longer available and causes the error to log on the terminal. - Please refer to [1] and [2]. [PR]: https://github.com/odoo/odoo/pull/281275 [1]: https://github.com/odoo/odoo/pull/248197/files#diff-f3528e61bb9aa2d24d9b57cddafb7429d21216ba29f9dc7e08c92bb617949911L218 [2]: https://pypdf.readthedocs.io/en/stable/meta/changelog-v1.html#details sentry-7663263079 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282159
`test_prepare_order_vals_rights` builds its PoS user with stock.`group_stock_user`. Until 19.2 `point_of_sale` depended on `stock_account`, so stock was always installed and the xmlid resolved. Since 6a56bd10cec7 split stock out of PoS, the module no longer pulls in stock, and `env.ref `raises "External ID not found in the system" when the module is tested alone. The group was never needed: the test only calls `_prepare_invoice_vals`, which reads the symbol as sudo and touches no stock record
Original PR description
`test_prepare_order_vals_rights` builds its PoS user with stock.`group_stock_user`. Until 19.2 `point_of_sale` depended on `stock_account`, so stock was always installed and the xmlid resolved. Since 6a56bd10cec7 split stock out of PoS, the module no longer pulls in stock, and `env.ref `raises "External ID not found in the system" when the module is tested alone. The group was never needed: the test only calls `_prepare_invoice_vals`, which reads the symbol as sudo and touches no stock record. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282859
The PoS client draws the QR code itself, but `showQR` was feeding it the result of `build_qr_code_url`, which is not a payment payload but the URL of the report rendering one: /report/barcode/?barcode_type=QR&quiet=0&width=128&height=128&value=... Scanning the code therefore gave the bank app a report path instead of the payment data. All methods going through `res.partner.bank` were affected: `sct_qr`, `emv_qr`, `id_qr` and `ch_qr`. Add `build_qr_code_value`, returning the value th
Original PR description
The PoS client draws the QR code itself, but `showQR` was feeding it the result of `build_qr_code_url`, which is not a payment payload but the URL of the report rendering one:
/report/barcode/?barcode_type=QR&quiet=0&width=128&height=128&value=...
Scanning the code therefore gave the bank app a report path instead of the payment data. All methods going through `res.partner.bank` were affected: `sct_qr`, `emv_qr`, `id_qr` and `ch_qr`.
Add `build_qr_code_value`, returning the value the barcode controller would have encoded, and use it in the PoS. This also fixes `default_qr`, the offline fallback. `get_qr_code_url` is renamed to `get_qr_code_value` as it no longer returns a URL.
task-6465442
Forward-Port-Of: odoo/odoo#282220**Steps to reproduce:** - Configure a Belgian company on a database without demo data - Install Accounting - From Accounting settings, activate Peppol - Use "Odoo Demo ID" as "Peppol EAS" **Issue:** The activation fails while tryings to activate Peppol in production mode. As `Odoo Demo ID` is used, it should activate Peppol in demo mode without issue, but the selected value is not taken into account. **Cause:** In this commit https://github.com/odoo/odoo/commit/6f8c2526a00d, `peppol
Original PR description
**Steps to reproduce:** - Configure a Belgian company on a database without demo data - Install Accounting - From Accounting settings, activate Peppol - Use "Odoo Demo ID" as "Peppol EAS" **Issue:**…
**Steps to reproduce:** - Configure a Belgian company on a database without demo data - Install Accounting - From Accounting settings, activate Peppol - Use "Odoo Demo ID" as "Peppol EAS" **Issue:** The activation fails while tryings to activate Peppol in production mode. As `Odoo Demo ID` is used, it should activate Peppol in demo mode without issue, but the selected value is not taken into account. **Cause:** In this commit https://github.com/odoo/odoo/commit/6f8c2526a00d, `peppol_eas` and `peppol_endpoint` have been renamed to `routing_scheme` and `routing_endpoint`. In the process, some logic has been lost. Previously, the "Peppol Registration" wizard had a related field to the `peppol_eas` field of the company partner. When selecting `Odoo Demo ID` in the wizard, it was also updating the related field to `odemo`. After the refactoring, the related field of the wizard has been replaced by a computed stored field without an inverse method. So changing the value in the wizard doesn't impact the `routing_scheme` field of the company partner that is not set to `odemo`. opw-6421240 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Steps to reproduce: - Install `l10n_fr_pdp` and `Accounting` > Switch to `FR Company` - Activate `French electronic invoicing` - Create New Invoice with `FR Company` as Customer - Send > unchecked French E-Invoicing (Demo) Traceback: `AttributeError: 'res.partner' object has no attribute '_get_pdp_receiver_identification_info'` In this REF [PR], we removed the `_get_pdp_receiver_identification_info` method and replaced it with the `l10n_fr_is_pdp` field, but we missed updating it here
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` and `Accounting` > Switch to `FR Company` - Activate `French electronic invoicing` - Create New Invoice with `FR Company` as Customer - Send > unchecked French E-Invoicing (Demo) Traceback: `AttributeError: 'res.partner' object has no attribute '_get_pdp_receiver_identification_info'` In this REF [PR], we removed the `_get_pdp_receiver_identification_info` method and replaced it with the `l10n_fr_is_pdp` field, but we missed updating it here. Solution: Replaced the removed `_get_pdp_receiver_identification_info` method with `l10n_fr_is_pdp`. [PR]: https://github.com/odoo/odoo/commit/5c3dde7f36609a74ffed8357c11a648d85942bdd#diff-a9b0aba990a93514e74372976dd8c77cda07db893324a0a2fad8a9027ec0b1da opw-6443303
The fix proposed in #274619 was not properly adapted for saas-19.4 and onwards as we changed the class name of the chart menu (see https://github.com/odoo/o-spreadsheet/pull/7861). Task-6441988 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
The fix proposed in #274619 was not properly adapted for saas-19.4 and onwards as we changed the class name of the chart menu (see https://github.com/odoo/o-spreadsheet/pull/7861). Task-6441988 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
Steps to reproduce: 1. Install `l10n_pe` 2. Create and set the current company to the Peru company 3. In mobile view, try to create a contact 4. Fill in the identification number type to RUC Issue: - The field of VAT is collapsed and not visible Cause: - The VAT div `vat_div` is displayed as a flex row (`o_row d-flex`) so the 'add identifier' button sits on the same line as the VAT field. https://github.com/odoo/odoo/blob/7d2d41fdef3446ca118290c1b31287887c0794db/addons/account/vie
Original PR description
Steps to reproduce: 1. Install `l10n_pe` 2. Create and set the current company to the Peru company 3. In mobile view, try to create a contact 4. Fill in the identification number type to RUC Issue: -…
Steps to reproduce:
1. Install `l10n_pe`
2. Create and set the current company to the Peru company
3. In mobile view, try to create a contact
4. Fill in the identification number type to RUC
Issue:
- The field of VAT is collapsed and not visible
Cause:
- The VAT div `vat_div` is displayed as a flex row (`o_row d-flex`) so the 'add identifier' button sits on the same line as the VAT field.
https://github.com/odoo/odoo/blob/7d2d41fdef3446ca118290c1b31287887c0794db/addons/account/views/partner_view.xml#L169-L171
Localizations based on `l10n_latam_base` also put an identification type field (e.g. RUC, DNI) in that same row, before the VAT field.
https://github.com/odoo/odoo/blob/7d2d41fdef3446ca118290c1b31287887c0794db/addons/l10n_latam_base/views/res_partner_view.xml#L14-L21
That identification type field carried the `oe_inline` class, which matched an unrelated, pre-existing mobile-only rule forcing any inline many2one to `width: 100% !important`.
https://github.com/odoo/odoo/blob/7d2d41fdef3446ca118290c1b31287887c0794db/addons/web/static/src/views/form/form_controller.scss#L999-L1001
Inside the flex row this left no space for its sibling, collapsing the VAT value input.
<table>
<tr>
<th width="50%">Before</th>
<th width="50%">After</th>
</tr>
<tr>
<td width="50%">
<img src="https://github.com/user-attachments/assets/12b1774f-2c60-4c89-a348-ccf514528552" width="100%">
</td>
<td width="50%">
<img src="https://github.com/user-attachments/assets/3f1571f1-8e88-41d3-89bb-b9e2ce1e85fc" width="100%">
</td>
</tr>
</table>
Solution:
- Drop the `oe_inline` class from the identification type field in `l10n_latam_base`'s partner view.
opw-6375655
Forward-Port-Of: odoo/odoo#275905Before this commit: --- The company logo is displayed above the background on the customer display. After this commit: --- The company logo is displayed only when there is no background or QR code to display. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281406
Original PR description
Before this commit: --- The company logo is displayed above the background on the customer display. After this commit: --- The company logo is displayed only when there is no background or QR code to display. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281406
Issue: --- Adding a pickup-in-store delivery method to a sales order from the backend `Add shipping` wizard and clicking on the pickup point selector raises: Invalid props for component `LocationSelectorDialog`: `countryId` is not a number. Steps to reproduce: 1- Create a SO with a partner without country set. 2- Enable debug mode. 3- Use `Add shipping` wizard and choose pick-up delivery method. 4- Open the location selector. Cause: --- `PickupLocationMany2OneField.countryId` re
Original PR description
Issue: --- Adding a pickup-in-store delivery method to a sales order from the backend `Add shipping` wizard and clicking on the pickup point selector raises: Invalid props for component `LocationSelectorDialog`: `countryId` is not a number. Steps to reproduce: 1- Create a SO with a partner without country set. 2- Enable debug mode. 3- Use `Add shipping` wizard and choose pick-up delivery method. 4- Open the location selector. Cause: --- `PickupLocationMany2OneField.countryId` returns the `id` of `this.partnerRecord.country_id` which is `false` when the company is not set. This can be fixed by a safe optional chain access. opw-6321167 Forward-Port-Of: odoo/odoo#281720
Issue: --- On the product page, when the image layout is set to grid and only one image is there, the image doesn't take the full width of its container on mobile devices. A empty space appears next to it. Steps to reproduce: 1- Go to a product page with mlutiple images. 2- Switch the image layout from carousel to grid. 3- Remove extra images and keep only one image. 4- Open the page using mobile view in chrome. This can be fixed by forcing `width: 100%` explicitly on the image wrapp
Original PR description
Issue: --- On the product page, when the image layout is set to grid and only one image is there, the image doesn't take the full width of its container on mobile devices. A empty space appears next to it. Steps to reproduce: 1- Go to a product page with mlutiple images. 2- Switch the image layout from carousel to grid. 3- Remove extra images and keep only one image. 4- Open the page using mobile view in chrome. This can be fixed by forcing `width: 100%` explicitly on the image wrapper for `o_grid_solo`. opw-6265732 Forward-Port-Of: odoo/odoo#281728
In this commit: - Ensure event ticket information is preserved during self-order processing and use the configured ticket price when recomputing order line prices. - This prevents ticket prices from being replaced by the product price after proceeding to payment and keeps the amounts consistent across the payment page. Task:6375899 Forward-Port-Of: odoo/odoo#282530 Forward-Port-Of: odoo/odoo#275645
Original PR description
In this commit: - Ensure event ticket information is preserved during self-order processing and use the configured ticket price when recomputing order line prices. - This prevents ticket prices from being replaced by the product price after proceeding to payment and keeps the amounts consistent across the payment page. Task:6375899 Forward-Port-Of: odoo/odoo#282530 Forward-Port-Of: odoo/odoo#275645
Features or functions removed from Odoo
Current behavior before PR: - In [49f01db](https://github.com/odoo-dev/odoo/commit/49f01dbbe7a607b83865cab308e0dc8193ee9f0b), `getDefaultValueFromGlobalFilter` was introduced just for `GlobalFilterInput`. Desired behavior after PR is merged: - `GlobalFilterInput` no longer relies on this function, so remove the unused getter. Task: [6388147](https://www.odoo.com/odoo/project/2328/tasks/6388147) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submi
Original PR description
Current behavior before PR: - In [49f01db](https://github.com/odoo-dev/odoo/commit/49f01dbbe7a607b83865cab308e0dc8193ee9f0b), `getDefaultValueFromGlobalFilter` was introduced just for `GlobalFilterInput`. Desired behavior after PR is merged: - `GlobalFilterInput` no longer relies on this function, so remove the unused getter. Task: [6388147](https://www.odoo.com/odoo/project/2328/tasks/6388147) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277761
Miscellaneous changes
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for sub-variants like 'image_128' or 'image_1024'. The responsive fields replicate the exact file size and data footprint of the original large image, leading to heavy storage overhead and unnecessary frontend asset loading. Behavior after: Animated GIF images scale down and crop correctly to match requested r
Original PR description
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for…
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for sub-variants like 'image_128' or 'image_1024'. The responsive fields replicate the exact file size and data footprint of the original large image, leading to heavy storage overhead and unnecessary frontend asset loading. Behavior after: Animated GIF images scale down and crop correctly to match requested responsive dimensions and aspect ratios. Sub-variants take up significantly less space in the filestore, matching proportional dimensions without dropping or stripping the underlying animation loop. Large images that are smaller than requested boxes are safely left un-upscaled to maximize database deduplication. Root Cause: Historically, a legacy safeguard bypassed GIF resizing and cropping because older versions of the Pillow library did not gracefully handle multi-frame sequential image buffers. As a result, standard 'image.crop()', 'image.thumbnail()', or 'image.resize()' implementations would flatten multi-frame animated sequences down into a single, static first frame or throw dimension/mode mismatches during save operations. Fix: Intercept the image processing pipeline when encountering an asset identified as a GIF where 'is_animated' evaluates to True. Implemented a unified, in-place multi-frame helper routine (`_apply_gif_operation`) using PIL's 'ImageSequence.Iterator' to cleanly step through, normalize to a uniform color mode (RGBA), duplicate, and modify each animation frame individually. This single helper handles sequential workflows for both 'crop' and 'thumbnail' operations while preserving individual frame duration arrays and native loop metadata. Both 'resize' and 'crop_resize' leverage this logic to achieve precise dimensions cleanly. Crucially, upscaling (expanding) is intentionally unsupported for animated GIFs. Forcing a low-resolution, 256-color indexed animation to stretch beyond its native dimensions forces heavy color dithering across every single frame. This breaks the sequential LZW pattern compression, causing the resulting file sizes to skyrocket catastrophically. The logic utilizes thumbnail boundaries to completely block this expansion, protecting the filestore from accidental bloat. Benchmark: -------------------------------------------------------------------------------------------- | GIF size | Variant | Size Before (KB) | Size After (KB) | |---------------|--------------------|--------------------------|-----------------------| | (2.5MB) | image_1024 | 2475.87 | 2475.87 | | | image_128 | 2475.87 | 257.93 | |---------------|--------------------|--------------------------|-----------------------| | (3.8MB) | image_1024 | 3724.93 | 3724.93 | | | image_128 | 3724.93 | 463.62 | |----------------|-------------------|--------------------------|-----------------------| | (442KB) | image_1024 | 432.49 | 432.49 | | | image_128 | 432.49 | 36.14 | |----------------|-------------------|--------------------------|-----------------------| | (3.6MB) | image_1024 | 3491.98 | 3491.98 | | | image_128 | 3491.98 | 1728.25 | |----------------|-------------------|--------------------------|-----------------------| opw-6232841 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#282831 Forward-Port-Of: odoo/odoo#273098
9 changes
Enhancements to existing features
This PR removes weekend days from dynamic update for the iot boxes. This allows to follow the support availabilities Forward-Port-Of: odoo/odoo#282780
Original PR description
This PR removes weekend days from dynamic update for the iot boxes. This allows to follow the support availabilities Forward-Port-Of: odoo/odoo#282780
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282024 Forward-Port-Of: odoo/odoo#281742
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282024 Forward-Port-Of: odoo/odoo#281742
Resolved issues and error corrections
This fix ensures the order details popup closes before the payment screen opens when a cashier chooses to edit a payment from a ticket. It prevents two screens from overlapping, making the checkout flow clearer and less confusing for users.
Original PR description
Steps to reproduce: ----------- - Validate an order, then open it from the ticket screen - Open the order details popup, click "Edit Payment" - Redirected to PaymentScreen, but the order details popup stays open on top of it Cause: --------- OrderDetailsDialog (opened via the dialog service) and PaymentScreen (opened via pos.navigate) are two separate stacks. Navigating to PaymentScreen does not close the dialog. Fix: -------------- Call dialog.closeAll() before pos.editPayment(order) in the editPayment callback passed to OrderDetailsDialog, so the dialog closes before navigating to PaymentScreen. task-6463084 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The link preview popover now gives users a larger clickable area for the magic wand icon, making it easier to use and better aligned with accessibility guidance. The hover feedback has also been improved, and the dark theme edit button now looks clearer as a button.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#282534 Forward-Port-Of: odoo/odoo#276929
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521 Forward-Port-Of: odoo/odoo#260276
Original PR description
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521 Forward-Port-Of: odoo/odoo#260276
Issue: --- On the product page, when the image layout is set to grid and only one image is there, the image doesn't take the full width of its container on mobile devices. A empty space appears next to it. Steps to reproduce: 1- Go to a product page with mlutiple images. 2- Switch the image layout from carousel to grid. 3- Remove extra images and keep only one image. 4- Open the page using mobile view in chrome. This can be fixed by forcing `width: 100%` explicitly on the image wrapp
Original PR description
Issue: --- On the product page, when the image layout is set to grid and only one image is there, the image doesn't take the full width of its container on mobile devices. A empty space appears next to it. Steps to reproduce: 1- Go to a product page with mlutiple images. 2- Switch the image layout from carousel to grid. 3- Remove extra images and keep only one image. 4- Open the page using mobile view in chrome. This can be fixed by forcing `width: 100%` explicitly on the image wrapper for `o_grid_solo`. opw-6265732 Forward-Port-Of: odoo/odoo#281728
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called at right time (when canceling a combo order)" ### Cause: Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely Without `static props`, Owl skips a
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790In this commit: - The feedback screen was not scaling properly on Android devices and tablet displays, causing content to appear too small or overflow. - Fixed by making the checkmark and text sizes responsive using units so the layout adapts correctly across different screen sizes. Task: 6420543 Forward-Port-Of: odoo/odoo#282539 Forward-Port-Of: odoo/odoo#279328
Original PR description
In this commit: - The feedback screen was not scaling properly on Android devices and tablet displays, causing content to appear too small or overflow. - Fixed by making the checkmark and text sizes responsive using units so the layout adapts correctly across different screen sizes. Task: 6420543 Forward-Port-Of: odoo/odoo#282539 Forward-Port-Of: odoo/odoo#279328
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116
Original PR description
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282042 Forward-Port-Of: odoo/odoo#274963
20 changes
Enhancements to existing features
This update adds automated tests for the Mollie payment option in Point of Sale, covering both the backend and the POS interface. It helps catch issues earlier and reduces the risk of payment-related regressions affecting customers.
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282024 Forward-Port-Of: odoo/odoo#281742
The IoT box update schedule no longer runs on weekends. This better matches support availability and reduces the chance of updates happening when help may not be available.
Original PR description
This PR removes weekend days from dynamic update for the iot boxes. This allows to follow the support availabilities Forward-Port-Of: odoo/odoo#282780
Revert the receipt tax summary design back to the 19.0 format, ensuring that the base amount is always displayed for each tax group. Before this commit, when all tax groups shared the same tax base, the base amount was hidden, leading to a flat tax listing. Now, the template always renders the tax groups in the format: "Tax [Name] on [Base Amount] [Tax Amount]" task-id: 6296906 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-
Original PR description
Revert the receipt tax summary design back to the 19.0 format, ensuring that the base amount is always displayed for each tax group. Before this commit, when all tax groups shared the same tax base, the base amount was hidden, leading to a flat tax listing. Now, the template always renders the tax groups in the format: "Tax [Name] on [Base Amount] [Tax Amount]" task-id: 6296906 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270749
Resolved issues and error corrections
This change makes sure the suggestion a user clicks in the message composer is the one that gets selected, even when the list updates at the same time. It prevents cases where typing and clicking quickly could leave the typed text in place instead of the chosen person or item.
Original PR description
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two members of the channel and typing "Pyn" drops one of them: owl assigns the filtered options one frame before it patches the list, so a click in between looks up index 1 in a list of one option, finds nothing and returns. This commit passes the rendered option to the click handler, keeping the index lookup as a fallback so that the signature stays the same on a stable version. https://runbot.odoo.com/odoo/error/946154 Forward-Port-Of: odoo/odoo#282897
This change ensures employees shown in the Gantt view are limited to the companies currently selected by the user. It prevents an access error that could happen when unrelated employees were displayed and the system tried to load their availability data.
Original PR description
Before this change, searching on hr.employee could return either employees from the selected company_ids, or employees managed by the current user. This means that sometimes, employees not in the currently selected company_ids could be shown (e.g.: on the gantt view). This caused issues, like, if on the gantt view, it shows employees from outside the company, then the gantt view will try to access the employee's resource (to get their unavailabilities). Since `resource.resource` is scoped only based on the company_ids, then we don't have the right to access them -> this leads to a traceback Since it makes little sense to show employees from outside the companies we selected (it should filter them!), I removed that from the domain in the `ir.access.csv` file Tests (of the gantt bug) have been added in enterprise. task-5502544
The website editor now shows dynamic snippet filter names in the user’s preferred language instead of automatically using the website language. This makes the editing experience clearer and more consistent for multilingual sites.
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#280152 Forward-Port-Of: odoo/odoo#275390
This change fixes an error that could stop Peppol disconnection from completing for companies using the French PDP module. It ensures the module accepts the same reset options as the standard process, preventing a runtime failure when Peppol settings need to be cleared.
Original PR description
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
This change restores a small component definition needed by automated POS tests, preventing false failures during order-cancel flows. It does not change the customer experience, but it keeps the Point of Sale test suite reliable and unblocks builds.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790This update corrects how combo items are linked during self-ordering, ensuring each selected combo product stays under the right parent item. It helps prevent mix-ups in combo orders and makes the ordering experience more reliable for customers and staff.
Original PR description
Be sure that combo product of the current line belong to its combo parent line. Forward-Port-Of: odoo/odoo#282809 Forward-Port-Of: odoo/odoo#281741
When a combo meal is split into individual items, each item is now placed under the correct course in the restaurant order view. If all items from a course are removed, that course is removed too, keeping the order display accurate and easier to manage.
Original PR description
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521 Forward-Port-Of: odoo/odoo#260276
This update fixes an issue where adding a new saved payment method through the Authorize payment provider could fail. The payment is now saved correctly, improving the customer checkout and portal experience.
Original PR description
Issue: --- Authorize payment tokenization doesn't work. Steps: 1- Setup authorize payment provider. 2- Using portal page, add a new payment method for the user. The created payment method is not…
Issue: --- Authorize payment tokenization doesn't work. Steps: 1- Setup authorize payment provider. 2- Using portal page, add a new payment method for the user. The created payment method is not saved. Cause: --- The issue was introduced in efc2788dfccd13ee6feb309430ff57e49664ff97. Before that, we were calling `_tokenize` before voiding the tx. In that PR, the `_tokenize` call was moved to `_process()`, after `_apply_updates()`. So now what happens is that we void the tx, then call `_tokenize()`. Inside tokenize we try to create a customer profile, which fails because the tx is already voided. Fix: --- We can fix it by calling `_tokenize()` once before voiding the tx. The redundant tokenize call inside the general payment tx `_process` is rendered ineffective by two safeguards: 1- There is a check for `tx.tokenize`, which neutralizes double tokenization: https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment/models/payment_transaction.py#L754-L755 https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment/models/payment_transaction.py#L893-L896 2- If `token_id` is already set, no token value is returned: https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment_authorize/models/payment_transaction.py#L237-L243 opw-6426847 Forward-Port-Of: odoo/odoo#281014
The link preview popover now gives the edit/magic wand control a larger clickable area and a hover effect, making it easier to find and use. In dark mode, the Edit button background has also been adjusted so it stands out properly against the popover.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#282534 Forward-Port-Of: odoo/odoo#276929
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was mi
Original PR description
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was missing from the report template if self-billing is enabled. ***Fix*:** * Add the missing condition so that the self-billing header is displayed when **Self Billing** is enabled on the journal. * For reference, here is the [Document](https://www.gesetze-im-internet.de/ustg_1980/__14.html) link. Ticket [link](https://www.odoo.com/odoo/project.task/6281066) opw-6281066 Forward-Port-Of: odoo/odoo#282664 Forward-Port-Of: odoo/odoo#272857
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with "TypeError: this.pos.autoCourseAllocation is not a function". Cause: b86126bbfb17105323a8ac972cb5062b95325fc4 moved autoCourseAllocation and cleanAutoCourseAllocation out of ProductScreen (point_of_sale) into the PosStore patch of pos_restaurant, but kept the two call sites in point_of_sale's
Original PR description
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with…
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with "TypeError: this.pos.autoCourseAllocation is not a function". Cause: b86126bbfb17105323a8ac972cb5062b95325fc4 moved autoCourseAllocation and cleanAutoCourseAllocation out of ProductScreen (point_of_sale) into the PosStore patch of pos_restaurant, but kept the two call sites in point_of_sale's ProductScreen._barcodeProductAction, now routed through this.pos. Both methods therefore only exist when pos_restaurant is installed, so on a plain shop configuration the call throws. The other call site, ProductScreen.addProductToOrder, is patched in pos_restaurant itself, which is why only the barcode path is affected. Runbot installs every module, so the patch is always loaded there and the crash went unnoticed. Also restore the argument forwarding in the pos_restaurant PosOrder.removeOrderline patch introduced by the same commit: it declares deep but called super.removeOrderline(line), dropping it. PosStore.breakCombo is the only caller passing deep=false. opw-6478112 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282919
task-6468432 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
task-6468432 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
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list neve
Original PR description
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list never brings it back. Note that the same race is reported on saas-19.1, where the tour crashes on `dispatchEvent` of null instead, as the `dragFiles` helper there queries the dropzone once where `dropFiles` waits for it. This commit waits for the mention list to close before the drag. https://runbot.odoo.com/odoo/error/946097 Forward-Port-Of: odoo/odoo#282716
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing
Original PR description
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax…
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing the ZUGFeRD template into the Accounting tab of his contact) 4. Send it and see that the tag <ram:CategoryCode> is setted as E instead of G ### Cause of the issue: The logic assigning the 'G' and 'K' tax category codes was only triggered if the supplier was located within the EEA. If the supplier was outside the EEA, the code bypassed this block entirely and fell back to the default 'E' code for 0% taxes. ### Reason to introduce the fix: Update the condition to trigger when either the supplier or the customer is in the EEA. This ensures that cross-border transactions involving at least one EEA party correctly evaluate and apply the 'G' (Export outside the EU) category code. Also the case supplier not in eea with VAT filled in + customer in eea + RC tax with amount != 0 is fixed now (letter G reported instead of S). ### Documentation: [eInvoicing technical guidance document_v1.pdf](https://github.com/user-attachments/files/30831749/eInvoicing.technical.guidance.document_v1.pdf) opw-6407399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282497 Forward-Port-Of: odoo/odoo#281245
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is
Original PR description
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never`…
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is raised. Root cause: --- - In `_is_add_to_cart_allowed()`[1], the method calls `_get_contextual_price()` [2] to check if the product's price is zero when `prevent_zero_price_sale` is enabled. - However, `_get_contextual_price()` is called without the no-variant attribute values in the context, so it does not account for their `price_extra`. For a product with list price as 0 and attribute with extra price, the price is incorrectly computed as 0, causing `_is_add_to_cart_allowed()` to return `False`. Solution: --- - Before calling `_is_add_to_cart_allowed()`, set the product's context with the no-variant attribute values via `_get_product_price_context()`, so that `_get_contextual_price()` correctly includes the price extra in its computation. [1]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/controllers/cart.py#L117-L120 [2]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/models/product_product.py#L149-L150 opw-6365566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282705 Forward-Port-Of: odoo/odoo#278620
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the catalog. Issue: --- - Long UoM names are not fully visible in the catalog view. Root cause: --- - The outer `<div>` has `d-flex` but lacks `w-100`, causing it to overflow its container. Solution: --- - Added `w-100` to the outer `<div>` to prevent overflow. - Adjusted the quantity s
Original PR description
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the…
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the catalog. Issue: --- - Long UoM names are not fully visible in the catalog view. Root cause: --- - The outer `<div>` has `d-flex` but lacks `w-100`, causing it to overflow its container. Solution: --- - Added `w-100` to the outer `<div>` to prevent overflow. - Adjusted the quantity selector layout for better visibility. Before: --- <img width="388" height="141" alt="image" src="https://github.com/user-attachments/assets/dafae08a-3c9d-4163-8894-daa2e4d26f62" /> After: --- <img width="382" height="154" alt="image" src="https://github.com/user-attachments/assets/abd6f034-be4b-49bf-be9c-c9779de0f30d" /> Enterprise PR: https://github.com/odoo/enterprise/pull/121139 opw-6253382 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282565 Forward-Port-Of: odoo/odoo#267118
10 changes
Enhancements to existing features
Some generic validation errors raised by core account models lack enough context to identify which record caused the issue, making FEC imports harder to troubleshoot. This commit improves the two error cases identified for this use case: - `account.account._check_account_code` now includes the invalid account code in the error message. - `account.move.write` now includes the move name/reference and displays human-readable field labels instead of technical field names when attempting to modi
Original PR description
Some generic validation errors raised by core account models lack enough context to identify which record caused the issue, making FEC imports harder to troubleshoot. This commit improves the two…
Some generic validation errors raised by core account models lack enough context to identify which record caused the issue, making FEC imports harder to troubleshoot. This commit improves the two error cases identified for this use case: - `account.account._check_account_code` now includes the invalid account code in the error message. - `account.move.write` now includes the move name/reference and displays human-readable field labels instead of technical field names when attempting to modify read-only fields on posted entries. Although motivated by FEC import, these are generic core validations, so the improvements are implemented at the source to benefit all callers rather than only the FEC import flow. Enrichment is scoped to the two cases above, other constraints/errors across these models are intentionally left unchanged for now, since editing core error messages more broadly should be done deliberately and on a case-by-case basis, not as a blanket rewrite task-5346068 Forward-Port-Of: odoo/odoo#281746
This PR handles 2 cases : ===== PART 1 ===== Self-billing bill sequences should be unique per partner, as implemented in v19+. This PR backports that behavior to 17.0. ===== PART 2 ===== Previously, the `is_self_billing` option on `account.journal` was available only for purchase journals. This caused an issue when importing a self-billing invoice into a regular sales journal with quick edit mode (accounting firm) enabled. In such cases, the newly created invoices would use the self-
Original PR description
This PR handles 2 cases : ===== PART 1 ===== Self-billing bill sequences should be unique per partner, as implemented in v19+. This PR backports that behavior to 17.0. ===== PART 2 ===== Previously, the `is_self_billing` option on `account.journal` was available only for purchase journals. This caused an issue when importing a self-billing invoice into a regular sales journal with quick edit mode (accounting firm) enabled. In such cases, the newly created invoices would use the self-billing sequence pattern, leading to traceability issues. This PR allows the creation of self-billing sales journals to prevent this issue. task-6103142 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282062 Forward-Port-Of: odoo/odoo#259935
Resolved issues and error corrections
Fixed a sales invoicing issue where each new invoice could include the total paid so far instead of just the latest payment amount. This ensures customers are invoiced correctly after each partial payment, preventing over- and under-invoicing.
Original PR description
Steps to produce: --- - Install the `Sales` module. - In Settings, enable `Automatic Invoice`. - Also enable the Demo payment provider. - Create a sale order with a total of `800` and confirm it. -…
Steps to produce: --- - Install the `Sales` module. - In Settings, enable `Automatic Invoice`. - Also enable the Demo payment provider. - Create a sale order with a total of `800` and confirm it. - Generate a payment link for `200` from the gear icon and pay it. - Generate a second payment link for `300` and pay it. - Generate a final payment link for the remaining `300` and pay it. Issue: --- - After the first payment (200), an `invoice of 200` is created. Correct. - After the second payment (300), an` invoice of 500` is created instead of 300. - After the third payment (300), an `invoice of 100` is created instead of 300. Root cause: --- - The down payment invoice uses `order.amount_paid`, the cumulative sum of all transactions on the order, instead of the amount of the latest payment. This causes invoices to be sized off the running total instead of the individual payment delta. Fix: --- - Compute the invoice amount as `order.amount_paid - order.amount_invoiced` (the unpaid) instead of passing the cumulative `amount_paid` directly. opw-6324036 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273099
This change makes an automated image upload test more reliable by giving it a little more time to detect the uploaded image. It reduces random test failures on busy systems, helping keep build and deployment checks stable.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 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#281200
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to produce: - Install `l10n_ar_stock` with demo data - Switch Company to `(AR) Exento` - Create a warehouse - Configuration > Operation Types > Delivery Orders - Set Document Type to `'(94) MAILING X' `and try to save ## Observed Behavior: The fields 'CAI' and 'CAI Expiration Date', which repre
Original PR description
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to…
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to produce: - Install `l10n_ar_stock` with demo data - Switch Company to `(AR) Exento` - Create a warehouse - Configuration > Operation Types > Delivery Orders - Set Document Type to `'(94) MAILING X' `and try to save ## Observed Behavior: The fields 'CAI' and 'CAI Expiration Date', which represent the authorization code and expiration date issued by the government, are currently configured as required fields. **Expected Behavior:** As specified on the [government site](https://www.argentina.gob.ar/normativa/nacional/resoluci%C3%B3n-1415-2003-81316/actualizacion#:~:text=Los%20datos%20indicados%20en%20el%20inciso%20a%29%2C%20puntos%207%2C%2010%2C%2011%2C%2012%20y%2013%2C%20s%C3%B3lo%20ser%C3%A1n%20para%20los%20remitos%20clase%20%27R%27%2E): > > 12. Printing authorization code, preceded by the acronym 'CAI No. ...'. > 13. Expiration date of the receipt, preceded by the legend 'Expiration Date ...' > > 'The data indicated in section a), points 7, 10, 11, 12 and 13, will only be for 'R' class delivery notes.' These statements indicate that the information mentioned in points 12 and 13, including the **CAI** and **CAI Expiration Date** fields, is applicable only to **'R'** class delivery notes. Therefore, for class X delivery notes, these fields should be optional rather than required. ## Root Cause: According to [1], the field is configured as a required field when a Document Type ID is selected. This configuration causes the **CAI** and **CAI Expiration Date** fields to become mandatory, regardless of the document type requirements defined by the government specification. [1]- https://github.com/odoo/odoo/blob/62b05c4ea61942072b6b1fb420fe3efedb11ed14/addons/l10n_ar_stock/views/stock_picking_type_views.xml#L11-L16 ## Solution: Apply constraints that align with the government specifications, allowing the CAI and CAI Expiration Date fields to remain optional for document types where they are not required. opw-6359503 Forward-Port-Of: odoo/odoo#275533
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list neve
Original PR description
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list never brings it back. Note that the same race is reported on saas-19.1, where the tour crashes on `dispatchEvent` of null instead, as the `dragFiles` helper there queries the dropzone once where `dropFiles` waits for it. This commit waits for the mention list to close before the drag. https://runbot.odoo.com/odoo/error/946097 Forward-Port-Of: odoo/odoo#282716
Issue: --- Authorize payment tokenization doesn't work. Steps: 1- Setup authorize payment provider. 2- Using portal page, add a new payment method for the user. The created payment method is not saved. Cause: --- The issue was introduced in efc2788dfccd13ee6feb309430ff57e49664ff97. Before that, we were calling `_tokenize` before voiding the tx. In that PR, the `_tokenize` call was moved to `_process()`, after `_apply_updates()`. So now what happens is that we void the tx, then ca
Original PR description
Issue: --- Authorize payment tokenization doesn't work. Steps: 1- Setup authorize payment provider. 2- Using portal page, add a new payment method for the user. The created payment method is not…
Issue: --- Authorize payment tokenization doesn't work. Steps: 1- Setup authorize payment provider. 2- Using portal page, add a new payment method for the user. The created payment method is not saved. Cause: --- The issue was introduced in efc2788dfccd13ee6feb309430ff57e49664ff97. Before that, we were calling `_tokenize` before voiding the tx. In that PR, the `_tokenize` call was moved to `_process()`, after `_apply_updates()`. So now what happens is that we void the tx, then call `_tokenize()`. Inside tokenize we try to create a customer profile, which fails because the tx is already voided. Fix: --- We can fix it by calling `_tokenize()` once before voiding the tx. The redundant tokenize call inside the general payment tx `_process` is rendered ineffective by two safeguards: 1- There is a check for `tx.tokenize`, which neutralizes double tokenization: https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment/models/payment_transaction.py#L754-L755 https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment/models/payment_transaction.py#L893-L896 2- If `token_id` is already set, no token value is returned: https://github.com/odoo/odoo/blob/fffd987cc98d1ea0cd04e24dda2ed8b64a219cdc/addons/payment_authorize/models/payment_transaction.py#L237-L243 opw-6426847 Forward-Port-Of: odoo/odoo#281014
Before this commit, "mesh peer to peer connections" fails at random on a loaded machine, counting fewer connections than its ten users make: [toBe] expected values to be strictly equal > Expected: 90 > Received: 81 This happens because the test counts the peers as soon as its addPeer calls resolve. addPeer awaits the readiness promise of the peer, which also resolves, with false, when that peer is disconnected. A connection slow to open reaches the recovery watchdog, which te
Original PR description
Before this commit, "mesh peer to peer connections" fails at random on a loaded machine, counting fewer connections than its ten users make:
[toBe] expected values to be strictly equal
> Expected: 90
> Received: 81
This happens because the test counts the peers as soon as its addPeer calls resolve. addPeer awaits the readiness promise of the peer, which also resolves, with false, when that peer is disconnected. A connection slow to open reaches the recovery watchdog, which tells the other side to drop the peer, drops it locally and adds it back without awaiting it. The awaited promises can therefore all be settled while recovered peers are still connecting.
This commit waits for the mesh to reach its full size before counting, so that a recovery in flight no longer decides the result. With the browser CPU throttled, the test fails about half of its runs before this commit, and none after.
Forward-Port-Of: odoo/odoo#282719## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The employee accrues on 6 days per week instead of 5 (Sunday is correctly skipped. Only Saturday is wrong). ## Expected behavior: The employee accrues only on the 5 working days (Mon–Fri) → 5 grants per week. Saturday and Sunday should add nothing. ## Setup: - Working schedule: Standard 40h/week, M
Original PR description
## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The…
## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The employee accrues on 6 days per week instead of 5 (Sunday is correctly skipped. Only Saturday is wrong). ## Expected behavior: The employee accrues only on the 5 working days (Mon–Fri) → 5 grants per week. Saturday and Sunday should add nothing. ## Setup: - Working schedule: Standard 40h/week, Monday–Friday, 08:00–17:00. - All timezones set to Australia/Brisbane (UTC+10) and matching: employee, working schedule, and user are all the same timezone. - Accrual plan milestone: accrue 5 Hours, Daily, "At the end of the accrual period", "Based on worked time = Yes". ## Steps to reproduce: - Create the working schedule and accrual plan above, with the calendar timezone set to Australia/Brisbane. - Assign the accrual allocation to an employee, Starting on a Monday. - On the Time Off dashboard, use "Balance at the (date)" to project the balance day by day across a weekend (Friday → Saturday → Sunday → Monday). ## Cause of the issue: Accrual period boundaries were built as naive UTC midnights instead of local calendar midnights. ## Fix: Localize accrual period boundaries in the employee/resource timezone before calling resource calendar APIs. This bug is reproducible in multiple versions. PRs for: - v19.0: https://github.com/odoo/odoo/pull/279029 - v18.0: https://github.com/odoo/odoo/pull/279036 opw-6316062 Forward-Port-Of: odoo/odoo#279029
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xm
Original PR description
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm…
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XX is invalid according to its datatype 'String' - The actual length is less than the MinLength value` **Expected behavior:** The refund should be processed successfully regardless of whether the original payment was made by credit card or eCheck (ACH) **Why this happens:** - The `refund()` method in `AuthorizeAPI` builds the refund request using a `creditCard` payment payload - When the original transaction was an ACH/eCheck payment, the `creditCard` key is absent from the transaction details returned by Authorize.net - The resulting request is rejected by Authorize.net because it does not satisfy the minimum length constraint for `cardNumber` **Fix:** - Detects whether the original payment used `creditCard` or `bankAccount` from the transaction details and build the appropriate payload according to Authorize.net API documentation: https://developer.authorize.net/api/reference/index.html#payment-transactions-credit-a-bank-account opw-6359726 Forward-Port-Of: odoo/odoo#277742
9 changes
Enhancements to existing features
Peppol errors are now shown as separate, easy-to-read items instead of one technical line. Known error codes are translated into plain-language explanations so users can better understand the issue and what to do next.
Original PR description
Before this commit, Peppol error messages (e.g. Schematron errors) were logged in the chatter as a single unformatted line and without any humanization. The errors were too technical and the user could not easily know what action to take. This PR splits the raw error payload into individual entries, maps known error codes to human-readable explanations, and renders them as an HTML list in the chatter. task-6144909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276029 Forward-Port-Of: odoo/odoo#265253
Resolved issues and error corrections
This change increases the waiting time in an automated image upload test so it has enough time to detect the uploaded image on slower systems. It helps prevent random test failures without changing the actual user experience.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 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#281200
Reverse-and-create credit notes now correctly produce exchange rate difference and cash basis accounting entries when the original invoice is in a foreign currency. This ensures the books reflect the real financial impact immediately, without requiring a manual reset and repost of the credit note.
Original PR description
### Issue before this commit: When using the "Reverse and Create Invoice" feature on a posted invoice with a foreign currency and Cash Basis enabled, the expected Exchange Difference and Cash Basis…
### Issue before this commit: When using the "Reverse and Create Invoice" feature on a posted invoice with a foreign currency and Cash Basis enabled, the expected Exchange Difference and Cash Basis tax entries are not generated upon the automatic reconciliation. The credit note is successfully created and reconciled with the original invoice, but the P&L exchange difference and the cash basis transition lines are completely missing. Currently, the only workaround is to manually reset the generated credit note to draft and re-post it, which forces the system to correctly calculate the currency rate differences and generate the missing entries. ### Steps to reproduce the issue: 1. Download Accounting 2. Go to Settings > Cash basis. Tick it and set as 'Base Tax Received Account' an account like 201000 Current Liabilities 3. Go to Chart of Accounts > search your account (ex. 201000 Current Liabilities) and be sure the flag of 'Allow Reconciliation' is on 4. Go to Taxes > 15% sales > set 'Tax Exigibility' as Based on Payment and 'Cash Basis Transition Account' always as 201000 Current Liabilities 5. Go to Currencies and set a new currency like MXN inserting tax rates as: 1. 1 july 2026: 20$ 2. 15 july 2026: 15$ 6. Create a new invoice with price 100 and 15% tax, set MXN as currency for the journal, set the date as 1 july and confirm it 7. Click on 'Credit Note', then 'Reverse and Create Invoice' and confirm it 8. go back to the invoice and see that after the total amount there is a new line 'Reversed on...' 9. After that line there should also be the line with the Exchange Difference since the tax rates for MXN currency were different at the moment of the invoice and at the moment of the credit note. This is only created by resetting to draft the credit note and confirm it again. ### Cause of the issue: In the account.move.reversal wizard, when is_modify = True (Reverse and Create), the system triggers _reverse_moves with cancel=True. At the end of the _reverse_moves method, the newly created reverse moves are automatically posted and reconciled. However, this automatic posting is executed with move_reverse_cancel=True injected into the context: reverse_moves.with_context(move_reverse_cancel=cancel)._post(soft=False). When the reconciliation engine (_reconcile_plan_with_sync and _create_exchange_difference_moves) detects this specific context key, it intentionally bypasses the creation of both the exchange difference P&L moves and the cash basis entries, treating the reversal as a pure administrative cancellation rather than a financial operation with currency fluctuations. ### Reason to introduce the fix: To ensure financial accuracy and compliance, especially when cash basis and multi-currency are involved, a reversal on a different date must reflect the actual exchange rate fluctuations and properly trigger cash basis rules. By removing the move_reverse_cancel context injection during the automatic posting of the reverse moves, we allow the native reconciliation engine to evaluate the newly computed balance (based on the credit note's date) against the original invoice. This ensures that exchange differences and cash basis journal entries are automatically and accurately generated on the first attempt. opw-6399867 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix stops users from deleting the image in a card cover while leaving behind an empty placeholder. It prevents the editor from getting into an inconsistent state that could trigger errors when adjusting cover image options.
Original PR description
It was possible to remove the image inside a card cover while keeping the figure wrapper. The card option would then still consider that there was a cover image even though the image was gone, which could also lead to a traceback. Steps to reproduce: - Insert the `s_three_columns` snippet - Click on the image of one card - Either press "Enter", "Delete", "Backspace" - Hover the "Cover Image" options => The image is removed but the `<figure>` is still there, so the option is still considered active (leading to a traceback) task-6081728 Forward-Port-Of: odoo/odoo#280086
Steps to produce: --- - Install the `Sales` module. - In Settings, enable `Automatic Invoice`. - Also enable the Demo payment provider. - Create a sale order with a total of `800` and confirm it. - Generate a payment link for `200` from the gear icon and pay it. - Generate a second payment link for `300` and pay it. - Generate a final payment link for the remaining `300` and pay it. Issue: --- - After the first payment (200), an `invoice of 200` is created. Correct. - After the sec
Original PR description
Steps to produce: --- - Install the `Sales` module. - In Settings, enable `Automatic Invoice`. - Also enable the Demo payment provider. - Create a sale order with a total of `800` and confirm it. -…
Steps to produce: --- - Install the `Sales` module. - In Settings, enable `Automatic Invoice`. - Also enable the Demo payment provider. - Create a sale order with a total of `800` and confirm it. - Generate a payment link for `200` from the gear icon and pay it. - Generate a second payment link for `300` and pay it. - Generate a final payment link for the remaining `300` and pay it. Issue: --- - After the first payment (200), an `invoice of 200` is created. Correct. - After the second payment (300), an` invoice of 500` is created instead of 300. - After the third payment (300), an `invoice of 100` is created instead of 300. Root cause: --- - The down payment invoice uses `order.amount_paid`, the cumulative sum of all transactions on the order, instead of the amount of the latest payment. This causes invoices to be sized off the running total instead of the individual payment delta. Fix: --- - Compute the invoice amount as `order.amount_paid - order.amount_invoiced` (the unpaid) instead of passing the cumulative `amount_paid` directly. opw-6324036 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273099
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list neve
Original PR description
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list never brings it back. Note that the same race is reported on saas-19.1, where the tour crashes on `dispatchEvent` of null instead, as the `dragFiles` helper there queries the dropzone once where `dropFiles` waits for it. This commit waits for the mention list to close before the drag. https://runbot.odoo.com/odoo/error/946097 Forward-Port-Of: odoo/odoo#282716
Calling `/shop/payment/validate` as a portal user with an empty cart confirms the empty sale order. Steps to reproduce: - Sign in as a portal user. - Add a product to the cart. - Remove the product. - Go to `/shop/payment/validate`. - The empty sale order is confirmed. opw-6430637 Forward-Port-Of: odoo/odoo#282335 Forward-Port-Of: odoo/odoo#280924
Original PR description
Calling `/shop/payment/validate` as a portal user with an empty cart confirms the empty sale order. Steps to reproduce: - Sign in as a portal user. - Add a product to the cart. - Remove the product. - Go to `/shop/payment/validate`. - The empty sale order is confirmed. opw-6430637 Forward-Port-Of: odoo/odoo#282335 Forward-Port-Of: odoo/odoo#280924
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the company of the vacuumed SVL. Steps to reproduce: - Enable multi-company and activate anglo-saxon accounting on two companies A and B. - In company B, on the product category: set FIFO costing + Automated valuation, and set the stock input / stock output / stock valuation accounts and the stock journa
Original PR description
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the…
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the company of the vacuumed SVL. Steps to reproduce: - Enable multi-company and activate anglo-saxon accounting on two companies A and B. - In company B, on the product category: set FIFO costing + Automated valuation, and set the stock input / stock output / stock valuation accounts and the stock journal. The Stock Output account must have "Allow Reconciliation" enabled. - In company B, on the product: set an Expense Account and set the Cost (e.g. 10.0) this is the price the delivery will be valued at while the stock is negative. The product must have no quantity on hand in company B. - While working in company B, sell and deliver 1 unit of that product: the delivery is valued at 10.0 and creates a negative valuation layer. - Still in company B, create and post the customer invoice of that sale, so the Stock Output line of the delivery entry gets reconciled with the Stock Output line of the anglo-saxon COGS entry of the invoice. - Switch the active company to A, and from there create a purchase order of that product for company B at a different price (e.g. 15.0), then validate the linked receipt into company B's warehouse. - The vacuum compensates the negative layer, but the resulting "Expenses Revaluation of ..." journal entry is posted in company A instead of company B. This fix forces the company context to `vacuum_svl.company_id` when fetching the product accounts and preparing the move lines so the JE is always created in the company of the SVL being vacuumed. opw-6066970 opw-6419188 Forward-Port-Of: odoo/odoo#259133
### Issue: When multiple partners share the same email address, `_mail_find_partner_from_emails` may resolve to the wrong partner when the input is a formatted email like "`Name <email>`" This affects use cases like email templates using `{{object.company_id.email_formatted}}` as sender, where the wrong company partner could be selected ### Cause: The lookup in `done_partners` only matched on `email_normalized`, which cannot distinguish partners sharing the same email but with different
Original PR description
### Issue: When multiple partners share the same email address, `_mail_find_partner_from_emails` may resolve to the wrong partner when the input is a formatted email like "`Name <email>`" This…
### Issue:
When multiple partners share the same email address, `_mail_find_partner_from_emails` may resolve to the wrong partner when the input is a formatted email like "`Name <email>`"
This affects use cases like email templates using `{{object.company_id.email_formatted}}` as sender, where the wrong company partner could be selected
### Cause:
The lookup in `done_partners` only matched on `email_normalized`, which cannot distinguish partners sharing the same email but with different names
The `email_formatted` field carries both name and email, allowing an exact match when the input is a formatted email
### Steps to reproduce:
- Install `account`
- Create an Email Template (Applies to: account.move, From: {{object.company_id.email_formatted}})
- Create a second company B with the same email as the default (e.g. info@yourcompany.com)
- In Settings (logged in as company B), set a Fiscal Position (e.g. US Taxable)
- Create an Invoice on company B
- In the chatter, click Send message, click the expand arrows button, use the three dots menu to select the template
- Send and check the Sender in the chatter
Before the fix, the sender resolves to the default company even though the invoice belongs to company B
opw-6260992
Forward-Port-Of: odoo/odoo#26950912 changes
Enhancements to existing features
The default waiting time used by some web test helpers has been increased so tests can better cope with slower or busier machines. This should reduce false failures in automated testing without affecting normal successful runs.
Original PR description
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests…
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests give 10 seconds. 430 call sites in addons reach these three helpers and 29 pass an explicit timeout, so 12 frames is what the other 401 get. The problem is that 12 frames is less than what the client needs on a loaded machine. Measured on "should remove file from html editor if removed from attachment list", on the wait that follows the Full composer button: - 5 to 7 frames on an idle machine; - 11 to 18 frames over 8 runs with the machine at load 10 to 20, 5 of the 8 above the 12 frames the default allows. Those 5 are failing runs, and the same test at load 13 to 29 fails 6 runs out of 6 with the 200 milliseconds, 0 out of 6 with 10 seconds. Note that a longer timeout costs nothing on a green build: the wait ends on the frame the DOM matches, so it only delays the report of a test that was going to fail anyway. Hoot fails the test itself after 5 seconds, 15 in test_js.py, which keeps bounding a wait that never resolves. This commit raises the default to 10 seconds, the delay a tour step already gets in macro.js and the one contains() and expect.waitForSteps already have. https://runbot.odoo.com/odoo/error/946094
In France, some drom-com (Guadeloupe, Martinique and Réunion) needs to use pdp just like France. So we should add those 3 for the computation of `peppol_eas`, so it will autocomplete to **France FRCTC Electronic Address**. task-6344558 Forward-Port-Of: odoo/odoo#278272
Original PR description
In France, some drom-com (Guadeloupe, Martinique and Réunion) needs to use pdp just like France. So we should add those 3 for the computation of `peppol_eas`, so it will autocomplete to **France FRCTC Electronic Address**. task-6344558 Forward-Port-Of: odoo/odoo#278272
Resolved issues and error corrections
This fix ensures the system always includes the required sign-up type when generating a token. It prevents sign-up links from failing or behaving inconsistently, improving the reliability of user invitation and account creation flows.
Original PR description
A `signup_type` is required to generate a token. Task-6452339
This change removes deprecated Peppol EAS codes from the options available on partner records and during Peppol registration. It helps prevent users from selecting invalid identifiers that could cause registration or communication issues.
Original PR description
Peppol EAS codes 0037, 0213, 9955, and 0193 are deprecated or removed from the Peppol specification but are still present in the selection field on stable branches, allowing users to register invalid identifiers. See: [eas codes](https://docs.peppol.eu/edelivery/codelists/v9.7/Peppol%20Code%20Lists%20-%20Participant%20identifier%20schemes%20v9.7.html) Before: - deprecated EAS codes were listed alongside valid ones in the partner's available Peppol EAS options, allowing users to select an outdated identifier for new or duplicated partners, or during Peppol registration. After: - Excluded deprecated EAS codes from the available Peppol EAS selection list on partners, preventing users from selecting them for new or duplicated partners, or during Peppol registration. Removed Deprecated codes in Master: odoo/odoo#271288 Task [link](https://www.odoo.com/odoo/project.task/6299691) task-6299691
## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The employee accrues on 6 days per week instead of 5 (Sunday is correctly skipped. Only Saturday is wrong). ## Expected behavior: The employee accrues only on the 5 working days (Mon–Fri) → 5 grants per week. Saturday and Sunday should add nothing. ## Setup: - Working schedule: Standard 40h/week, M
Original PR description
## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The…
## Current behavior: On a Monday–Friday working schedule, a Daily accrual plan that is based on worked time grants accrued time on Saturday as well, even though Saturday is not a working day. The employee accrues on 6 days per week instead of 5 (Sunday is correctly skipped. Only Saturday is wrong). ## Expected behavior: The employee accrues only on the 5 working days (Mon–Fri) → 5 grants per week. Saturday and Sunday should add nothing. ## Setup: - Working schedule: Standard 40h/week, Monday–Friday, 08:00–17:00. - All timezones set to Australia/Brisbane (UTC+10) and matching: employee, working schedule, and user are all the same timezone. - Accrual plan milestone: accrue 5 Hours, Daily, "At the end of the accrual period", "Based on worked time = Yes". ## Steps to reproduce: - Create the working schedule and accrual plan above, with the calendar timezone set to Australia/Brisbane. - Assign the accrual allocation to an employee, Starting on a Monday. - On the Time Off dashboard, use "Balance at the (date)" to project the balance day by day across a weekend (Friday → Saturday → Sunday → Monday). ## Cause of the issue: Accrual period boundaries were built as naive UTC midnights instead of local calendar midnights. ## Fix: Localize accrual period boundaries in the employee/resource timezone before calling resource calendar APIs. This bug is reproducible in multiple versions. PRs for: - v19.0: https://github.com/odoo/odoo/pull/279029 - v18.0: https://github.com/odoo/odoo/pull/279036 opw-6316062
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the company of the vacuumed SVL. Steps to reproduce: - Enable multi-company and activate anglo-saxon accounting on two companies A and B. - In company B, on the product category: set FIFO costing + Automated valuation, and set the stock input / stock output / stock valuation accounts and the stock journa
Original PR description
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the…
When the FIFO vacuum creates the "Expenses Revaluation" journal entry for an anglo-saxon delivery whose cost is adjusted by a later receipt, the JE was built using `env.company` instead of the company of the vacuumed SVL. Steps to reproduce: - Enable multi-company and activate anglo-saxon accounting on two companies A and B. - In company B, on the product category: set FIFO costing + Automated valuation, and set the stock input / stock output / stock valuation accounts and the stock journal. The Stock Output account must have "Allow Reconciliation" enabled. - In company B, on the product: set an Expense Account and set the Cost (e.g. 10.0) this is the price the delivery will be valued at while the stock is negative. The product must have no quantity on hand in company B. - While working in company B, sell and deliver 1 unit of that product: the delivery is valued at 10.0 and creates a negative valuation layer. - Still in company B, create and post the customer invoice of that sale, so the Stock Output line of the delivery entry gets reconciled with the Stock Output line of the anglo-saxon COGS entry of the invoice. - Switch the active company to A, and from there create a purchase order of that product for company B at a different price (e.g. 15.0), then validate the linked receipt into company B's warehouse. - The vacuum compensates the negative layer, but the resulting "Expenses Revaluation of ..." journal entry is posted in company A instead of company B. This fix forces the company context to `vacuum_svl.company_id` when fetching the product accounts and preparing the move lines so the JE is always created in the company of the SVL being vacuumed. opw-6066970 opw-6419188 Forward-Port-Of: odoo/odoo#259133
When importing UBL invoices that contain document-level allowances or charges with percentage taxes, the tax values were not linked to their corresponding `TaxSubtotal` group (`related_taxes_values`). As a result, the tax correction step (`_import_ubl_invoice_fix_taxes_amounts`) was unaware of document-level taxes, which caused wrong tax corrections. opw-6388544
Original PR description
When importing UBL invoices that contain document-level allowances or charges with percentage taxes, the tax values were not linked to their corresponding `TaxSubtotal` group (`related_taxes_values`). As a result, the tax correction step (`_import_ubl_invoice_fix_taxes_amounts`) was unaware of document-level taxes, which caused wrong tax corrections. opw-6388544
**Steps to reproduce:** (18.0 only) - Go to Contacts app - Pick a contact record - Change Salesperson on contact to Marc Demo - Click on "Send Message" without sending (to show the suggested recipients) - Remove Marc Demo from the followers to ensure he appears in suggested recipient checkboxes - Click the second name on the checkbox list - It will uncheck the first name on the list **Issue:** `t-attf-id="{{ props.recipient.id }}_checkbox"` in `SuggestedRecipients` produces `id="unde
Original PR description
**Steps to reproduce:**
(18.0 only)
- Go to Contacts app
- Pick a contact record
- Change Salesperson on contact to Marc Demo
- Click on "Send Message" without sending (to show the suggested recipients)
- Remove Marc Demo from the followers to ensure he appears in suggested recipient checkboxes
- Click the second name on the checkbox list
- It will uncheck the first name on the list
**Issue:**
`t-attf-id="{{ props.recipient.id }}_checkbox"` in `SuggestedRecipients` produces `id="undefined_checkbox"` and defaults to the same value each time on click.
**Fix:**
As `id` is not defined on the recipient, try to use `props.recipient.persona?.id` instead.
opw-6395530> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent commit, leaving no common ancestor with 18.0. A PR in that state cannot be reopened, so this one continues from a clean branch with the exact same change. The review discussion is in that PR, and the rename asked for there is included here. ### Steps to reproduce 1. Go to `Accounting > Customers > Invoi
Original PR description
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent…
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent commit, leaving no common ancestor with 18.0. A PR in that state cannot be reopened, so this one continues from a clean branch with the exact same change. The review discussion is in that PR, and the rename asked for there is included here. ### Steps to reproduce 1. Go to `Accounting > Customers > Invoices` and create an invoice on a given journal, leaving it in draft. For the clearest case, leave it with no invoice line. 2. Go to `Accounting > Configuration > Journals`, open that journal and archive it. 3. `_check_auto_post_draft_entries` raises: *"You can not archive a journal containing draft journal entries. To proceed: 1/ click on the top-right button 'Journal Entries' from this journal form 2/ then filter on 'Draft' entries 3/ select them all and post or delete them through the action menu"*. 4. Follow those steps: click the `Journal Entries` smart button on the journal form. ### Current behaviour The list comes up empty, so the user concludes the error message is wrong, while the draft entries do exist. The instructions cannot be followed: - The smart button opens `action_account_moves_all_a`, which is named **"Journal Items"** and targets **`account.move.line`**, not `account.move`. The label of the button and the name of the action it opens do not match. - That action defaults to `search_default_posted: 1`, so no draft record is listed. - Draft entries with **no line at all** — commonly created through the incoming mail alias of a journal — have no `account.move.line`, so they stay invisible in that view even after switching the filter. - The action menu of a move line list offers no way to post or delete the entries, and the action sets `create: 0`. - The filter is labelled **"Unposted"**, not "Draft". The offending entries are only reachable through `Accounting > Accounting > Journal Entries`, filtering by journal and by "Unposted". ### Expected behaviour The error should point to a view where the records blocking the archiving are actually listed and actionable. ### This PR Two changes, the validation itself is unchanged: - The error message now points to `Accounting > Accounting > Journal Entries` and uses the real filter name, "Unposted". - The smart button of the journal form is renamed to **"Journal Items"**, so its label matches the action it opens and no longer suggests it lists journal entries. This was asked for in the review of the previous PR. Targeted at 18.0 because that is where the misleading message is being hit in practice; it is identical on 19.0 and master. If a translatable string change does not qualify for the stable series, tell me and I will retarget to master.
Due to the following commit: 01efd8cfcce3269ca6b88d549a670b08a90298cb, a division by zero error is raised when a 100% discount is used with a price-included tax. When the discount is 100%, it is impossible to retrieve the original tax amount before discount using a simple multiplication as the current raw_tax_amount_currency is zero. In that case, we need to recompute taxes using the original unit price before discount. opw-6242701 --- I confirm I have signed the CLA and read the PR
Original PR description
Due to the following commit: 01efd8cfcce3269ca6b88d549a670b08a90298cb, a division by zero error is raised when a 100% discount is used with a price-included tax. When the discount is 100%, it is impossible to retrieve the original tax amount before discount using a simple multiplication as the current raw_tax_amount_currency is zero. In that case, we need to recompute taxes using the original unit price before discount. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
**Steps to reproduce:** - Create a tax that affects the base of the subsequent ones - Create an invoice with this tax and another one on the same line **Issue:** In "_aggregate_base_line_tax_details", the tax amount from the first tax should be included in the following values of the second tax: - raw_total_excluded - raw_total_excluded_currency - target_total_excluded - target_total_excluded_currency - total_excluded - total_excluded_currency But it is not. opw-6235909
Original PR description
**Steps to reproduce:** - Create a tax that affects the base of the subsequent ones - Create an invoice with this tax and another one on the same line **Issue:** In "_aggregate_base_line_tax_details", the tax amount from the first tax should be included in the following values of the second tax: - raw_total_excluded - raw_total_excluded_currency - target_total_excluded - target_total_excluded_currency - total_excluded - total_excluded_currency But it is not. opw-6235909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Description of the issue this PR addresses: We don't support colspan/rowspan in the editor, so tables containing them can break other functionality that assumes a rectangular grid (equal cell count per row). This PR expand any rowspan/colspan into individual cells on insert. opw-6347233 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Description of the issue this PR addresses: We don't support colspan/rowspan in the editor, so tables containing them can break other functionality that assumes a rectangular grid (equal cell count per row). This PR expand any rowspan/colspan into individual cells on insert. opw-6347233 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
3 changes
Resolved issues and error corrections
The Send & Print flow will no longer preselect “Send via PEPPOL” when the customer is missing required PEPPOL recipient details. This avoids failed invoice sending and makes sure users only see PEPPOL as an option when the recipient can actually receive it.
Original PR description
When opening the Send & Print wizard on a customer invoice, the "Send via PEPPOL" option could be checkeden even for a partner that is not able to receive Peppol documents because its Peppol EAS…
When opening the Send & Print wizard on a customer invoice, the "Send via PEPPOL" option could be checkeden even for a partner that is not able to receive Peppol documents because its Peppol EAS and/or Endpoint are not set. Steps to reproduce: - Configure the company for Peppol sending. - Create a customer as follows: - Country: Belgium - VAT: none - Format: BIS Billing 3.0 - Peppol e-address (EAS): 0208 - Poppol Endpoint: none - Post a customer invoice for that partner. - Click Send & Print. Issue: "Send via PEPPOL" is checked by default, so sending the invoice fails with "The partner is missing Peppol EAS and/or Endpoint identifier.". Analysis: A partner with no EAS/Endpoint at all may still be treated as valid for the send&print wizard, only to fail later at send time where the EAS/Endpoint are effectively mandatory. To avoid blocking automated flows (Connect+), the system should mark such partners as invalid as soon as their Peppol EAS or Endpoint is missing opw-5717362
Before this commit it was impossible to avoid rendering the full report when an invoice had too many lines. This made it impossible to send some Peppol documents. To avoid this we add a system parameter that stops the document generation and prints a limit-reached page instead, avoiding the wkhtmltopdf time/memory issues. OPW-6352345 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Before this commit it was impossible to avoid rendering the full report when an invoice had too many lines. This made it impossible to send some Peppol documents. To avoid this we add a system parameter that stops the document generation and prints a limit-reached page instead, avoiding the wkhtmltopdf time/memory issues. OPW-6352345 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Steps to Reproduce: - Create an applicant (with or without an email address). - Move the applicant to the *Hired* stage. - Create an employee from the applicant. - The employee’s work email is automatically being set to the company email. ### Fix: - Explicitly set work_email to False. - work_email=False is required as we have this compute method: https://github.com/odoo/odoo/blob/d84196003012d68b63b8a1564deb43e43c9ebd68/addons/hr/models/hr_employee_base.py#L200-L204 here work_
Original PR description
### Steps to Reproduce: - Create an applicant (with or without an email address). - Move the applicant to the *Hired* stage. - Create an employee from the applicant. - The employee’s work email is automatically being set to the company email. ### Fix: - Explicitly set work_email to False. - work_email=False is required as we have this compute method: https://github.com/odoo/odoo/blob/d84196003012d68b63b8a1564deb43e43c9ebd68/addons/hr/models/hr_employee_base.py#L200-L204 here work_email and partner's email is being sync. Task: 6124112 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr