Daily updates from Odoo
Wednesday, August 19, 2026
214 changes
27 changes
Resolved issues and error corrections
Generated ISO 20022 payment files now include the state/province and second address line when available on vendor or employee addresses. This helps avoid bank rejections, especially for North American wire transfers that require complete beneficiary address details.
Original PR description
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street…
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street complement (suite, unit, ...) therefore never appear in the generated file, even when they are set on the partner, and there is no way to fix it from the record. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Return the state code and street2 alongside the other address components, from the partner for the base implementation and from the employee private address for the hr one, so the payment engine can write them in the PstlAdr block. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Companion enterprise PR emitting the state in the generated file: odoo/enterprise#127958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282620 Forward-Port-Of: odoo/odoo#282518
Point of Sale now avoids creating extra positive and negative down payment lines when taking a down payment on a sales order that already has one. This keeps POS orders clearer and prevents confusing duplicate payment adjustments for staff and customers.
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#281397 Forward-Port-Of: odoo/odoo#275653
When a production order was already confirmed, updating its bill of materials could leave outdated manufacturing steps in place or fail to reflect changes. This fix ensures confirmed orders stay aligned with the latest bill of materials so production instructions remain accurate.
Original PR description
### Steps to reproduce: - Create a product with a bom and 2 operations - Create an MO for 1 unit of that product - Confirm the MO - On the bom, delete the second operation and modify the first…
### Steps to reproduce: - Create a product with a bom and 2 operations - Create an MO for 1 unit of that product - Confirm the MO - On the bom, delete the second operation and modify the first operation on anything else than the company, name or workcenter - Go back to the MO, click the "Update Bom" button > The second operation is not unlinked and the first operation is not updated ### Cause of the issue: The `action_update_bom` updates the move raws and operations of the MO via the `_link_bom`: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L1214-L1218 For draft MO's all the work of these updates is done via the compute methods and by deleting all the records unrelevant to the new bom: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2603-L2626 And, in that case all the workorders that are not linked to an operation of the bom are expected to be deleted. However, when the MO is not in draft, the update of operations is expected to be performed here: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2647-L2664 However, since the operation of the bom has been deleted, the workorder that is expected to be deleted is not linked to any operation and hence does not satisfy the condition to be deleted: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2663-L2664 Concerning the non update of operations, it happens because the MO's operation are only updated on the three fields: `company_id`, `workcenter_id`, `name`: https://github.com/odoo/odoo/blob/31df5033e31c193b4576ef37dfbc5fc683817bc5/addons/mrp/models/mrp_production.py#L2647-L2664 https://github.com/odoo/odoo/blob/31df5033e31c193b4576ef37dfbc5fc683817bc5/addons/mrp/models/mrp_production.py#L2628-L2629 However, many other changes can and are actually relevant. ### Note: Prior to commit 80e6ed658fb43584bc2fad673ca40d9af6cf0ab6 operations were archived on boms rather than deleted: https://github.com/odoo/odoo/blob/4a5270218fe6fd7d30edb6d684b3340dc7423bab/addons/mrp/views/mrp_routing_views.xml#L53-L55 As such they would still be linked to an operation (but unrelated to the present values of the bom) and hence would fall into the condition of being unlinked from the MO. Since the bom operations are no longer archived there is no way to determine if an operation used to be linked to a bom and we therefore need to chose between deleting all operations unrelated to the present bom or to keep them all (when the MO has been confirmed). Enterprise: https://github.com/odoo/enterprise/pull/120709 opw-6285878 opw-6261738 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280803 Forward-Port-Of: odoo/odoo#269747
When a combo meal is split into individual items, each item is now placed under its correct course automatically. If all items from a course are removed, that course is removed too, helping keep restaurant orders clear and accurate.
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#282255 Forward-Port-Of: odoo/odoo#260276
Refunds through Authorize.net now correctly handle both card and ACH/eCheck payments. This fixes a case where refunds could fail after settlement, helping businesses process returns without manual support or delays.
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#282810 Forward-Port-Of: odoo/odoo#277742
When users clicked a suggestion in the message composer, the system could sometimes keep the typed search text instead of inserting the chosen name. This fix ensures the suggestion shown on screen is the one selected, making mentions and similar autocomplete actions more reliable.
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 prevents the Point of Sale sample products from failing to load in setups where product attributes were removed or demo data is not present. It ensures the required attribute data is available first, so opening a new shop and loading sample items works reliably.
Original PR description
## Steps to Reproduce: 1. Install the **PoS** and **Sales** modules without demo data. 2. Settings > Enable **Variants**. 3. Sales > Products > Attributes > Delete "**Brand**" attribute. 4. Create a **Clothes Shop** and open the register. 5. Load the **Sample** products. ## Error: `ParseError - while parsing /home/odoo/src/odoo/saas-19.4/addons/product/data/product_attribute_demo.xml:5, somewhere inside...` ## Cause: The `product_attribute_demo.xml` file references attributes that do not exist when the demo data is loaded, which raises an error. Before 19.4, the attributes were defined in the same file. After this commit https://github.com/odoo/odoo/commit/56942bcf34785e869c7648cf100c8818c5da0b6d, the attributes are defined separately in the `product_attribute_data.xml` file. ## Fix: This commit loads the data file before, ensure the referenced attributes are available when the demo file is processed. sentry-7640019804
This fix ensures electronic invoices use the correct tax category when a company in or outside the EEA bills a customer across borders. It prevents invoices from being labeled as exempt when they should be treated as export or reverse-charge cases, reducing the risk of incorrect e-invoice submissions.
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#282904 Forward-Port-Of: odoo/odoo#281245
When a sales order uses a fiscal position, advance payment invoices now use the account mapping defined by that fiscal position. This fixes cases where down payment invoices could post to the wrong account, helping ensure invoices and accounting entries follow the company’s tax/accounting rules.
Original PR description
How to reproduce: - In a Fiscal Position, map the Downpayment account set in the settings to anything else - Put that Fiscal Position on a SO. - On that SO, create a Downpayment invoice -> The regular Downpayment account is used on the Downpayment invoice, but it should have been mapped because of the Fiscal Position account mapping Solution: Pre-map the company's default down payment account using the Sales Order's Fiscal Position before passing it to the invoice line creation. This ensures the correct account mapping is always respected for advance payment invoices. Task-6212218 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281507 Forward-Port-Of: odoo/odoo#279464
When a subcontracted product is returned for exchange, the replacement items now go to warehouse stock instead of staying in the subcontracting location. The received quantity on the purchase order is also updated correctly, so the order reflects the full amount delivered.
Original PR description
Steps to reproduce ------------------ 1. Configure a product with a subcontracted BoM and a subcontractor. 2. Create a purchase order of 10 units for that product and confirm it. 3. Receive the 10…
Steps to reproduce ------------------ 1. Configure a product with a subcontracted BoM and a subcontractor. 2. Create a purchase order of 10 units for that product and confirm it. 3. Receive the 10 units. 4. On the receipt, use "Return for Exchange" on 3 units and validate both the return and the exchange receipt. Issue ----- After the exchange, the 3 units stay in the subcontracting location instead of reaching `WH/Stock`, and the received quantity on the purchase order line stays at 7 instead of 10. `mrp_subcontracting` overrides `_prepare_move_default_values` to force the move `location_dest_id` to the subcontractor location for every `is_subcontract` move: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/mrp_subcontracting/wizard/stock_picking_return.py#L20-L25 That is correct for the return, but the same override also runs for the exchange re-receipt, an `incoming` picking whose destination should be the stock location from `return_type.default_location_dest_id`: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/stock/wizard/stock_picking_return.py#L137-L153 The exchange move then goes from the subcontracting location back to itself, so validating it nets zero and `WH/Stock` never receives the units. Skipping the override when `new_picking.picking_type_id.code` is `incoming` lets the exchange land in stock. The received quantity must also count that receipt. `_should_count_for_quantity_received` only counts `supplier` or `transit` sources: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/stock/models/stock_move.py#L330-L331 so the exchange, sourced from the internal subcontracting location, is skipped while the return still subtracts its quantity. Counting subcontracting-sourced moves: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/mrp_subcontracting/models/stock_move.py#L312-L314 restores `qty_received` to 10. opw-6410978 Forward-Port-Of: odoo/odoo#282666 Forward-Port-Of: odoo/odoo#279431
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
16 changes
Resolved issues and error corrections
Payment files now include the state or province and second address line from vendor or employee address records. This helps prevent bank transfer rejections, especially in countries like the US and Canada where state or province details are often required.
Original PR description
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street…
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street complement (suite, unit, ...) therefore never appear in the generated file, even when they are set on the partner, and there is no way to fix it from the record. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Return the state code and street2 alongside the other address components, from the partner for the base implementation and from the employee private address for the hr one, so the payment engine can write them in the PstlAdr block. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Companion enterprise PR emitting the state in the generated file: odoo/enterprise#127958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282620 Forward-Port-Of: odoo/odoo#282518
This fixes several point-of-sale payment issues caused by an earlier internal renaming. It restores proper handling for Mercado Pago, Cashdro, Cashmatic, Safaricom, and bank QR payments so transactions do not remain stuck or fail to complete.
Original PR description
*: point_of_sale,pos_mercado_pago,pos_cashdro,pos_cashmatic, pos_safaricom d7a627160372 renamed the client-side payment interface attached to a pos.payment.method from `payment_terminal` to `payment_interface`, moved integrations off `payment_method_type` onto `payment_provider`, and renamed the `qr_code` type to `bank_qr_code`. Several call sites were left behind and now read attributes or compare against values that no longer exist, so they silently never match. Mercado Pago calls a method straight off the missing attribute, so an incoming webhook raises a TypeError and the payment line stays pending forever. The rest degrade silently: Cashdro and Cashmatic never cancel on Force Done, Safaricom never resolves the payment promise, and Bank QR lines left in `waiting` are no longer reset to `retry` when the session restarts, leaving them stuck. Use the existing `useBankQrCode` getter for the type check rather than repeating the literal. opw-6372208
The website editor now shows dynamic snippet filter names in the editor user's preferred language instead of the website's default language. This prevents confusion for editors working on multilingual websites where the public site language differs from their own interface language.
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#280743 Forward-Port-Of: odoo/odoo#275390
Store pickup locations are no longer shown as selectable delivery addresses during checkout. This prevents shoppers from accidentally choosing an internal pickup-point record instead of their own delivery address, keeping the checkout flow clearer and less error-prone.
Original PR description
Steps to produce: --- - Install `website_sale_collect` module. - Create and publish a product. - Add it to the cart and proceed to checkout. - Fill in the address and confirm. - Select a `pick-up in…
Steps to produce: --- - Install `website_sale_collect` module. - Create and publish a product. - Add it to the cart and proceed to checkout. - Fill in the address and confirm. - Select a `pick-up in store` delivery method. - Click the edit icon on the contact details. - Confirm without making any changes. Issue: --- - The pick-up point address appears as a selectable delivery address in the contact details list, which it should not. Root cause: --- - When a pick-up point is selected, `set_pickup_location` calls `_address_from_json` ([1]), which creates a child `res.partner` record with `type='delivery'` and sets `pickup_delivery_method_id` to identify it as a pick-up point address. Later, when the user returns to the address page, `_prepare_address_data` calls `_get_delivery_address_domain` ([2]) from `portal`. This method returns all child partners with `type='delivery'` without distinguishing between user-created delivery addresses and the auto-generated pick-up point addresses As a result, the pick-up point address incorrectly appears in the checkout address list. Solution: --- - As specified in [task], partners created through this flow should be archived. However, in the referenced [commit], the `active=False` flag was removed when creating the partner, causing newly created partners to remain active. Override `_get_delivery_address_domain` to exclude pick-up point addresses. Since auto-generated pick-up point addresses always have `pickup_delivery_method_id` set, they are filtered out from the checkout address list, while manually created delivery addresses remain unaffected. [1]https://github.com/odoo/odoo/blob/fb6298e50a7c8ded2800254e8715336eeb37deb5/addons/website_sale_stock/models/res_partner.py#L16-L72 [2]https://github.com/odoo/odoo/blob/fb6298e50a7c8ded2800254e8715336eeb37deb5/addons/portal/models/res_partner.py#L51-L55 [task]: https://www.odoo.com/odoo/project/49/tasks/3645144 [commit]: https://github.com/odoo/odoo/commit/fb74a371407ee19c6b1a3ab9f5a7b314978cb5cb opw-6356778 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
DIN 5008 business documents now show dates in the expected German, Austrian, and Swiss format regardless of the user’s language settings. Company footers also use the appropriate country-aware commercial register label, avoiding misleading German-specific text for Austrian and Swiss companies.
Original PR description
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document…
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Observed behavior (commercial register):**
* The footer always shows `HRB-Nr.:` regardless of whether the company has a commercial register entry.
* The abbreviation `HRB-Nr.:` appears even for Austrian and Swiss companies, where the commercial register number is a German-specific concept.
* In the company form view, the field is labeled generically as "Company ID" instead of "Commercial Register Number" for German companies.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Cause (commercial register):**
* The footer renders `company.company_registry` unconditionally with no country guard and no label.
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
**Fix (commercial register):**
* Remove the hardcoded `HRB-Nr.:` label from the footer and instead render `company.partner_id.company_registry_label` (which is country-aware).
* Update the duplicate contact warning message to use the country-aware label via `company.partner_id.company_registry_label`, backed by a new `_get_company_registry_labels` override in l10n_de that registers `Commercial Register Number` for `DE`.
* In the company form view (`l10n_de`), hide the generic "Company ID" field for German companies and show a relabeled instance with `string="Commercial Register Number"` instead.
opw-6392649
Forward-Port-Of: odoo/odoo#282964
Forward-Port-Of: odoo/odoo#279085This update makes the product variant setting available when only Point of Sale is installed. It ensures businesses on the OAF plan can access the same variant option seen in other areas, so the setup matches expected behavior and can be configured when needed.
Original PR description
If only PoS is installed (if you are on the OAF plan). The variants settings is unavailable and cannot be activated. Steps to reproduce: ------------------- * Install only PoS * Look for variant in settings > Observation: The option is not showing up Why the fix: ------------ The setting is just a copy of the other places where the settings is available. opw-6378568
This change corrects how self-order validates combo products, making sure each combo item is linked to the right parent combo line. It prevents incorrect combinations from being accepted and helps avoid order entry mistakes for customers using self-order kiosks.
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
Fixed an issue where clicking a suggested mention could keep the typed search text instead of inserting the selected name. This makes mention and autocomplete selections more reliable, especially when the list changes quickly while typing.
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
The shop now uses the same searchable product fields for both result matching and filter counts. This avoids cases where hidden HTML or technical text caused too many products to be processed, making search and filters more reliable for shoppers.
Original PR description
The `/shop` product results and facets use different search fields. In particular, facets search raw `website_description` HTML, causing terms such as `weight` to match CSS like `font-weight` and process far more products than are displayed. Use one shared field list for both paths: - `name` - `variants_default_code` - `description_sale` - `description_ecommerce` Stop searching `default_code`, internal `description`, and raw `website_description`. opw-6391984 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280720
This change makes an automated image upload test more reliable by giving it a little more time to detect the uploaded image. It helps prevent random test failures on slower or heavily used systems, improving overall build stability.
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
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
19 changes
Resolved issues and error corrections
Refunds for payments made through Authorize.net using eCheck/ACH now use the correct bank account refund details instead of credit card details. This prevents refund failures and helps businesses process customer refunds consistently across supported payment methods.
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
The attendance kiosk no longer loads a presence status script that is not used in that view. This reduces unnecessary resource loading and helps keep the kiosk experience lighter without changing its functionality.
Original PR description
This commit removes the hr_attendance_presence_status.js file from the kiosk bundle, as it is not needed in the kiosk view and can cause unnecessary loading of resources. task-6468972 Forward-Port-Of: odoo/odoo#282410
Argentine delivery operations using class X document types can now be saved without entering CAI authorization details, matching government rules that require those fields only for class R delivery notes. This removes an unnecessary blocker for affected warehouse configurations while keeping validation where it is legally needed.
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
Odoo now correctly shows employees' out-of-office return dates in Discuss, even when the viewer does not have access to the employee's company. This prevents missing availability information in sidebars, member lists, and chat banners, helping teams see colleague availability reliably.
Original PR description
*=hr_holidays,im_livechat,mail,test_discuss_full Out-of-office return dates were loaded through the partner's main user's employee_ids. That relation is company-filtered, so users without access to the employee's company did not receive leave_date_to in Discuss until opening the avatar card refreshed the data through another path. This commit fixes this behavior by loading leave_date_to from all employees linked to the partner's main user using sudo and exposing them through the all_employee_ids store relation. This makes the out-of-office indication consistently available in the sidebar, member list, and chat banner. task-6095661 Forward-Port-Of: odoo/odoo#282123 Forward-Port-Of: odoo/odoo#263149
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
12 changes
Resolved issues and error corrections
Vendor and employee payment addresses now include the state or province and second street line when generating ISO 20022 payment files. This helps prevent bank payment rejections, especially in regions such as the US and Canada where state/province information is required.
Original PR description
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street…
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street complement (suite, unit, ...) therefore never appear in the generated file, even when they are set on the partner, and there is no way to fix it from the record. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Return the state code and street2 alongside the other address components, from the partner for the base implementation and from the employee private address for the hr one, so the payment engine can write them in the PstlAdr block. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Companion enterprise PR emitting the state in the generated file: odoo/enterprise#127958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282620 Forward-Port-Of: odoo/odoo#282518
This fixes an issue where the calendar could show the wrong weekday for users in time zones where daylight saving time starts at midnight. Calendar headers now display the correct sequence of days, avoiding confusion when planning around those dates.
Original PR description
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day…
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day column right after the transition gets the wrong weekday name, duplicating the previous day's name. For ex. it renders "... THU THU FRI ..." instead of "... THU FRI SAT ...", for the week surrounding April 30th 2027. To fix this we add 1 hour to the Date before reading its weekday/day from it, mirroring the workaround FullCalendar itself adopted for this same bug. It has no effect on any ordinary day (adding 1h to a correct local midnight stays within the same calendar day), and it cannot overshoot into the next day since no real-world DST gap exceeds that margin. Note: This is a known bug (https://github.com/fullcalendar/fullcalendar/issues/7633), fixed in FullCalendar v6.1.17, a major version ahead of the v4.4.0, so the fix can't be applied directly without a full library upgrade. opw-6370140 Forward-Port-Of: odoo/odoo#279836 Forward-Port-Of: odoo/odoo#279343
This change ensures that when a user clicks a mention suggestion in the message composer, the name shown on screen is the one inserted. It prevents cases where the typed search text could remain instead of the selected contact, improving reliability when mentioning people with special characters in their names.
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
Italian simplified electronic invoices now include the required virtual stamp duty information and can be exported in the simplified format when the document type requires it. The change also prevents simplified invoices from being used for non-domestic or public administration partners, reducing compliance errors.
Original PR description
- Added the BolloVirtuale in the Simplified invoice template - Now it's possible to force the Simplified format on exported invoice when the `l10n_it_document_type` is set to a simplified one - Factored the Italian partner recognition (_l10n_it_edi_is_italian) - Added a check on the invoice, no simplified format for non-domestic / PA partners Task [link](https://www.odoo.com/odoo/project.task/6226436) task-6226436 Forward-Port-Of: odoo/odoo#282839 Forward-Port-Of: odoo/odoo#274493
Clicking a table of contents entry in the HTML editor now scrolls a bit further so the target heading is clearly visible, not just barely shown at the edge of the screen. This makes navigation in longer HTML content feel more reliable and easier to follow for users.
Original PR description
When clicking on a title in the TOC, we auto-scroll to that section of the HTML, allowing users to read that part. Since [1], scrollIntoView is replaced to consider top-aligned sticky elements. As a result, instead of scrolling to make it comfortable to read the section, it stops as soon as the title is visible. Unless you are really attentive at the bottom of the screen, it can look like the scrolling did not work. This commit computes the appropriate offset to make the TOC heading more visible after scrolling. [1]: https://github.com/odoo/odoo/commit/f5cf8565e7d09edd3a29fd95537381fb70d75785 Task-6394193 Forward-Port-Of: odoo/odoo#278304
This fixes an issue in the HTML editor where formatting from an outer table could incorrectly overwrite the colors of a table placed inside it. Business documents and web content with nested tables will now keep their intended visual styling after editing or normalization.
Original PR description
Problem: When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells…
Problem:
When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells belonging to the inner table. The inner table's own color is then discarded since its `td`s already have a value.
Cause:
`table.querySelectorAll("td")` returns every `td` in the entire subtree, not just the table's own direct cells.
Solution:
Scope the selected `td`s to `td.closest("table") === table`, so a table's color is only distributed to its own cells.
Steps to reproduce:
1. Add a `background-color` to an outer `table`.
2. Nest a `table` with a different `background-color` inside one of its cells.
3. Load/normalize the content in the editor.
4. Observe both tables' cells carry the outer table's color.
opw-6438972
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281850
Forward-Port-Of: odoo/odoo#281413DIN 5008 business documents now show dates in the expected German-style format for Germany, Austria, and Switzerland, regardless of the user's language settings. Company registry information is also shown only when relevant and uses country-appropriate wording, reducing confusion on official documents.
Original PR description
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document…
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Observed behavior (commercial register):**
* The footer always shows `HRB-Nr.:` regardless of whether the company has a commercial register entry.
* The abbreviation `HRB-Nr.:` appears even for Austrian and Swiss companies, where the commercial register number is a German-specific concept.
* In the company form view, the field is labeled generically as "Company ID" instead of "Commercial Register Number" for German companies.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Cause (commercial register):**
* The footer renders `company.company_registry` unconditionally with no country guard and no label.
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
**Fix (commercial register):**
* Remove the hardcoded `HRB-Nr.:` label from the footer and instead render `company.partner_id.company_registry_label` (which is country-aware).
* Update the duplicate contact warning message to use the country-aware label via `company.partner_id.company_registry_label`, backed by a new `_get_company_registry_labels` override in l10n_de that registers `Commercial Register Number` for `DE`.
* In the company form view (`l10n_de`), hide the generic "Company ID" field for German companies and show a relabeled instance with `string="Commercial Register Number"` instead.
opw-6392649
Forward-Port-Of: odoo/odoo#282964
Forward-Port-Of: odoo/odoo#279085Fixed 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
10 changes
Resolved issues and error corrections
Non-admin users can once again send Vietnamese electronic invoices through SInvoice after migrating from version 18. The fix restores the expected invoicing workflow while keeping administrative credential fields protected.
Original PR description
### Steps to Reproduce: 1). Install l10n_vn_edi_viettel ('Vietnam E-Invoicing') module in v18. 2). Migrate the database in any version above v18. 3). AccessError will appear while generating ('Send…
### Steps to Reproduce:
1). Install l10n_vn_edi_viettel ('Vietnam E-Invoicing') module in v18.
2). Migrate the database in any version above v18.
3). AccessError will appear while generating ('Send to SInvoice') on invoice for non-admin users.
### Issue:
- In v18, users were able to send and generate documents via (Send to SInvoice). Since v18.1 onwards, field access [check] is enforced during this flow, and since `l10n_vn_edi_username` is restricted to admin users only [here], non-admin users hit an AccessError as soon as
`_l10n_vn_edi_get_credentials_company` reads this field on`res.company`.
```py
You do not have enough rights to access the field "l10n_vn_edi_username" on Companies (res.company). Please contact your system administrator.
Operation: read
User: 12
Groups: allowed for groups 'Role / Administrator'
```
### Solution:
- This commit fixes the issue by adding a `sudo()` call on the company inside [_l10n_vn_edi_get_credentials_company] itself, so that non-admin users can successfully send and generate documents like in the previous version, without any hassle.
[check]: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/odoo/orm/models.py#L3384
[here]: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/l10n_vn_edi_viettel/models/res_company.py#L9
[_l10n_vn_edi_get_credentials_company]: https://github.com/odoo/odoo/blob/ecc267a231958c2dd99a7287c6bd1adbdbd22965/addons/l10n_vn_edi_viettel/models/account_move.py#L885
Ticket [link](https://www.odoo.com/odoo/project.task/6434854)
opw-6434854This fix ensures that when a down payment taken through Point of Sale is refunded, it is no longer counted again when the related sales order is settled or invoiced. This prevents customers from being charged twice and keeps the invoicing totals accurate.
Original PR description
The following commit resets qty_invoiced to zero on sale order lines paid by a POS order when that order is refunded. https://github.com/odoo/odoo/commit/ac39aa4f68dfc77011c39e468e3f60e0338a3c69 However, it does not handle the sale order line created for a refunded POS down payment. That line keeps `qty_invoiced` = -1, which causes the refunded amount to be included again when settling or invoicing the sale order. Steps to reproduce: - Create a sale order. - Pay a down payment through the POS. - Refund the down payment order from the POS. - Settle the remaining amount from the POS or invoice the sale order from the backend. Result: - The generated invoice includes the sale order total plus the refunded down payment. - Sale order `amount_invoiced` will be the down payment amount. Fix: - Delete the refunded downpayment to match the sale flow. - Include refunded down payments in the amount_invoiced computation. opw-6378891 Forward-Port-Of: odoo/odoo#278011
This change makes the peer-to-peer connection test wait until the full set of connections is established before measuring the result. It prevents random test failures on busy or slower machines, improving confidence in the chat system’s reliability.
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#282719This update removes an old, unused view attribute from the Philippine 2307 wizard form. It does not change how the form works, but it keeps the configuration cleaner and avoids compatibility issues with newer Odoo versions.
Original PR description
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly…
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly [state](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L150-L155) , [amount_tax_signed](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L229)
(e.g. `invisible=...`, `readonly=...`), the `modifiers` attribute is redundant and serves no purpose.
This attribute was never added manually by us — it was auto-generated by Odoo Studio when the default view was created. Studio's default views inject `modifiers` alongside the direct attributes. [Here](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-dfebe5a93e1b8880e88268b024be4c6f106d144b20298d7bb6c4ae09a18bafd0L67-L145)
Also the `modifiers` attribute was fully simplified [removed](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) starting from version 17.0, where views rely exclusively on direct attribute expressions (`invisible`, `readonly`, `required`) instead of the `modifiers` JSON encoding [main Patch](https://github.com/odoo/odoo/pull/104741) Keeping it around in the arch is therefore dead code with no effect.
However it needs to give the error on 17.0+ like this
```
ERROR LOG:
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_NOELEM: Expecting an element data, got nothing
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_INVALIDATTR: Invalid attribute modifiers for element field
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_EXTRACONTENT: Element tree has extra content: field
```
As the modifer has been remove from the field [common.rng](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) RelaxNG schema but modifiers set on fields here root tag is **form**, and the modifiers sit on fields inside a nested list. And Form views aren't RNG-validated from 17.0 till now —
[@validate('calendar', 'graph', 'pivot', 'search', 'list', 'activity')](https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/odoo/tools/view_validation.py#L314) has no form, and there's no [form_view.rng](https://github.com/odoo/odoo/tree/19.0/odoo/addons/base/rng).
Current senario
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer: it show the same view because of field property
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer still it shows the **modifiers="{'readonly':true, 'required':true}"** because the modifer is stay in the 14.0 but the 17.0 onwards it was not please see the scrrenshot its field preprty always.
<img width="1003" height="462" alt="image" src="https://github.com/user-attachments/assets/5e833924-b17c-417f-9e63-5a01c185f588" />
This Fix removes the unused `modifiers` attribute from the view arch, keeping only the direct attribute already present, with no functional change to the view's behavior.
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#281271
Forward-Port-Of: odoo/odoo#279976This 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
12 changes
Resolved issues and error corrections
This fix prevents an error when users change a product to a service after removing its unit of measure. It improves reliability in Inventory product setup by safely handling products without a unit configured.
Original PR description
Steps to replicate: 1. Install `stock`. 2. In Inventory > Configurations > Settings, enable the setting "Units of Measure". 3. Create a new product. 4. Remove the Unit. 5. Enable "Track by Inventory". 6. Swap Product Type to Service. A traceback error results. https://drive.google.com/file/d/1S_5Xdlhfe03hGaykewdIACmaaraCQcOw/view?usp=sharing A product's unit of measure's precision is passed to `float_is_zero` without first confirming that the unit of measure exists. opw-6172389 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
French customers with a valid SIREN or SIRET number are now correctly treated as business customers even when no VAT number is recorded. This keeps the French e-Invoicing option available for eligible invoices and avoids unnecessary manual workarounds.
Original PR description
**Steps to reproduce:** - Install module `l10n_fr_pdp` and configure French e-Invoicing. - Create a customer has a valid SIREN/SIRET (company_registry) but no VAT number. - Create an invoice for the customer and confirm the invoice. - Check the available sending methods. **Observed Behavior:** The French E-Invoicing option is disabled because the customer is identified as a B2C partner when no VAT number is set. **Cause**: The B2C detection relies on the partner's VAT number instead of its SIREN/SIRET. As a result, French companies without a VAT number but with a valid SIREN are classified as B2C. **Fix**: Determine whether a partner is B2C based on the presence of a valid SIREN/SIRET (derived from `company_registry`) instead of the VAT number. This correctly identifies French business partners that are eligible for French e-Invoicing even when they do not have a VAT number configured. opw-6357756
Saudi electronic invoices issued in SAR no longer include a duplicate tax total in the XML sent to ZATCA. This prevents validation warnings or errors for common Saudi invoices and helps businesses process compliant e-invoices more reliably.
Original PR description
Steps to reproduce: - Create an invoice in a Saudi company (currency SAR) - Process it with ZATCA and review the generated XML file - ZATCA reports a validation error/notification for duplicate tax values, because the XML contains two cac:TaxTotal elements holding the same amount and currency Cause of the issue: _l10n_sa_get_additional_tax_total_vals always appended a second TaxTotal node regardless of the invoice's currency. this extra node is only valid when the invoice currency differs from the company's accounting currency (SAR). Since most Saudi invoices are issued in SAR (same as the company currency), the second TaxTotal was an exact duplicate of the first one's total amount. Solution: Only add the additional TaxTotal node when the invoice currency differs from the company currency opw-6409881 Forward-Port-Of: odoo/odoo#279929
This update ensures that invoices using the DIN5008 layout keep the recipient address in the correct position when sent by post through Snailmail. As a result, letters can now pass Pingen’s validation and be sent successfully instead of failing during delivery.
Original PR description
**Steps to reproduce:** - Install l10n_din5008 and accountant. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer…
**Steps to reproduce:** - Install l10n_din5008 and accountant. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer invoice using the DIN5008 report layout. - Select Send by Post. - Enable Developer Mode and navigate to `Settings → Technical → Email → Snailmail Letters`. - Open the generated letter and send it. **Current behavior:** The letter fails to be sent to Pingen with the following error: An error occurred when sending the document by post. Error: ` The attachment of the letter could not be sent. Please check its content and contact the support if the problem persists.` **Cause:** For Snailmail documents, Pingen validates that the recipient address is located within the DIN5008 address window. The current l10n_din5008 report renders additional document information instead of the address in the address area, preventing the compliance validation to fail. **Fix:** When rendering the report for Snailmail, ensure that only the recipient address is displayed in the DIN5008 address window while suppressing the additional information that would otherwise occupy this area. This preserves the standard DIN5008 layout for regular reports while generating a Snailmail-compliant PDF that passes Pingen’s validation. **Reference:** [Pignen Recipient Address Validation Rule](https://help.pingen.com/en/fix-and-enhance-letters/issue-with-recipient-address#040201) Ticket [link](https://www.odoo.com/odoo/project.task/6387869) opw-6387869
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
4 changes
Resolved issues and error corrections
Odoo now shows the specific error details returned by Serbia’s eFaktura service when an invoice submission fails. This helps users understand why an invoice was rejected and resolve issues faster instead of seeing only a generic connection or HTTP error.
Original PR description
**Steps to reproduce:** - Install the Serbian EDI module `l10n_rs_edi`. - Configure eFaktura credentials on the company. - Create and confirm a Serbian customer invoice. - Send the invoice to…
**Steps to reproduce:**
- Install the Serbian EDI module `l10n_rs_edi`.
- Configure eFaktura credentials on the company.
- Create and confirm a Serbian customer invoice.
- Send the invoice to eFaktura.
**Observed Behavior:**
When the eFaktura API returns an HTTP error, Odoo only displays the generic exception generated by `requests`, for example an HTTP 400/500 error.
The actual error information returned by eFaktura in the response body is not shown to the user, making it difficult to understand why the invoice was rejected.
**Cause:**
`_l10n_rs_edi_send` catches `HTTPError`, `Timeout`, and `ConnectionError`, but the error message is built only from the Python exception.
For HTTP errors, the eFaktura API may return a response containing more precise information such as:
```json
{
ErrorCode: ...,
Message: ...
}
```
This response was not being used when displaying the error in Odoo.
**Fix:**
When an HTTP response is available and contains an eFaktura error payload, use the returned `ErrorCode` and `Message` as the error displayed on the invoice. Fallback to the existing connection/HTTP exception message when no usable API response is available.
opw - 6453653This fix ensures that when an image already linked to another record is copied, Odoo reuses the existing attachment instead of creating an unnecessary duplicate. This helps keep the database cleaner and avoids extra storage and clutter behind the scenes.
Original PR description
Copying an image attachment already linked to another record could leave a redundant duplicate behind instead of reusing the existing one. opw-6463012
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