Tuesday, September 1, 2026
29 changes · saas-19.4
Resolved issues and error corrections
The website shop search bar now shows its placeholder text in the visitor's selected language instead of always displaying "Search". This improves the multilingual shopping experience and avoids confusing customers browsing in other languages.
Original PR description
Problem: The search bar placeholder text is not being translated. Steps to reproduce: 1. Install e-Commerce 2. Go to Website > Configuration and add another language for the website 3. Go to Website > Shop 4. See how the search bar placeholder text is "Search" instead of being in the website's language Cause: The text was not extracted for translation because it is set inside `t-value=`. To be available for extraction, it should either be set inside `t-valuef.translate=` or should be the data content between the tags. opw-6486429 Forward-Port-Of: odoo/odoo#285011
Mobile invoice line cards now display the line description when no product is selected. This prevents blank cards, making invoices easier to review and edit from a phone.
Original PR description
Invoice lines can be created without a product. However, the mobile kanban view does not handle such lines properly and displays an empty card without a name or image. This commit adapts mobile kanban view to show invoice line's name when `product_id` is not set. Before | After -- | -- <img width="469" height="277" alt="image" src="https://github.com/user-attachments/assets/3b367581-b73d-4b12-a487-1a54c3b88470" /> | <img width="406" height="300" alt="image" src="https://github.com/user-attachments/assets/107d7294-90e8-49c6-826a-9be75c6b799f" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285608 Forward-Port-Of: odoo/odoo#284755
The Sales app now consistently hides product configuration edit buttons once a sales order is locked. This prevents users from appearing able to change configurable products, event tickets, or booths after confirmation, keeping locked orders consistent and protected from unintended edits.
Original PR description
### Steps to Reproduce: 1. Go to Sales > Configuration > Settings 2. Under Quotations & Orders, enable "Lock Confirmed Sales" 3. Now create a Quotation with 2 products, 1 with attributes and 1…
### Steps to Reproduce: 1. Go to Sales > Configuration > Settings 2. Under Quotations & Orders, enable "Lock Confirmed Sales" 3. Now create a Quotation with 2 products, 1 with attributes and 1 without 4. Confirm the order 5. Hover over the product with attributes and notice that it allows you to to edit, but hovering over the other product does NOT reveal the edit icon ### Issue: When a user has configured their database to lock sale orders, it should not be possible to edit the products once the order has been confirmed. It currently only happens for products that have attributes. While standard products cannot be edited in a locked state, a missing condition on configurable products allows the button to persist when hovering over the description column. This creates an inconsistent UI state where users appear to have access to modify some of the line items. ### Solution: To fix this, we updated the `hasConfigurationButton` getter in `sale_product_mixin.js` to evaluate the parent document's locked state. By adding `!this.props.record.model.root.data.locked` to the getter's return logic, the edit button is now globally hidden across all related widgets (such as `sale_label_text` and `sale_product_field`) when the sales order is locked. This ensures that configurable products properly respect the locked document restrictions just as standard products do. Additionally, this locked condition was applied to the method overrides in the `event_sale` and `event_booth_sale` modules, ensuring that event tickets and booths also hide their configuration buttons on locked orders.Additionally, this locked condition was applied to the method overrides in the event_sale and event_booth_sale modules, ensuring that event tickets and booths also hide their configuration buttons on locked orders. opw-6512288 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Uploading certain electronic vendor bills no longer fails when the supplier country is missing from the XML file. The system now safely uses the country already set on the supplier record, helping accounting teams process compliant invoices without manual file corrections.
Original PR description
Steps to reproduce: - Install accounting and create BE company - Create BIS3 xml where there's no country for AccountingSupplierParty - From BE company, upload the xml vendor bill Current behavior: Error when trying to upload xml Expected behavior: No error Cause of issue: Currently there's no check to see if a country exists in the BIS3 xml. This PR adds a check and adds a fallback to get the country attached to the partner record if there's none present in the xml opw-6498830 Forward-Port-Of: odoo/odoo#284862 Forward-Port-Of: odoo/odoo#284554
Appraisals now keep the generic template chosen by the user when they are confirmed or reset. This prevents records from being reassigned to the first available generic template, so filtering and reporting by the selected template remain accurate.
Original PR description
Issue: When a user selects a generic appraisal template other than the first one, confirming or resetting the appraisal silently replaces that selection with the first generic template. Filtering…
Issue: When a user selects a generic appraisal template other than the first one, confirming or resetting the appraisal silently replaces that selection with the first generic template. Filtering appraisals by the originally selected template then fails to return the appraisal. Steps to reproduce: * Configure multiple appraisal templates without department restrictions. * Create an appraisal and select a template other than the first one. * Confirm the appraisal. * Filter appraisals by the selected template. Cause: `_compute_appraisal_template()` only preserved templates directly linked to the appraisal's department. Generic templates have no department relation, so a valid selected template was discarded whenever the computation was triggered by a state dependent department recomputation. The generic fallback then stored the first template instead. https://github.com/odoo/enterprise/blob/5c57ccbb13269af28de0a6c7f35454be52424f43/hr_appraisal/models/hr_appraisal.py#L195-L209 Solution: We need to distinguish the generic default loaded on an unsaved form from a compatible generic template already stored on an appraisal. Preserve the latter across recomputations while retaining department template priority during creation and rejecting templates that no longer match the appraisal's department or company. opw-6449041 Forward-Port-Of: odoo/enterprise#127566
Pasting a copied URL over an existing link in the HTML editor no longer causes an error. This improves editing reliability for users working with links in website or content fields.
Original PR description
Steps to reproduce the issue: - Create a link in editor. - Copy another URL. - Select entire link. - Pasting copied link throws traceback. This issue happens after merging commit [1] where…
Steps to reproduce the issue:
- Create a link in editor.
- Copy another URL.
- Select entire link.
- Pasting copied link throws traceback.
This issue happens after merging commit [1] where `normalize_processors` callback returns nothing. After merging commit [2] each processor must return the original root if no processing is needed or processing is in place.
As a result, when this.processThrough("normalize_processors", container) is called from the `insert` method, the next processor in the chain uses `this.editable` as its default argument and removes the FEFF node, which is the anchor node. Later calling closestBlock(selection.anchorNode) returns null, resulting in the traceback. This PR aims to fix the traceback by returning the `root` in processor.
[1]: https://github.com/odoo/odoo/commit/be77a9a2003e09f4621d0ff774bf8749b326d037
[2]: https://github.com/odoo/odoo/commit/17d58d2fdf8da3a69c731fc5ea0d90b95e28efd6
task-6456004
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prFixed an issue where adding a new group in a grouped list view could trigger an error when totals or aggregated values were shown. This improves reliability for users organizing records, such as CRM contacts, by preventing an interruption during normal list management.
Original PR description
Adding a new group on a grouped list view with aggregates gives a traceback. This comes from `getFieldCurrencies` and `computeAggregates` which didn't guard for group with no currency aggregates (like a newly created group). Steps to reproduce: - open a list view (CRM) - group by a m2o (Contact) - click on 'Add a Contact' - press Enter => Traceback Forward-Port-Of: odoo/odoo#285664 Forward-Port-Of: odoo/odoo#285325
Installing the Ecuador electronic invoicing module now works reliably even when optional payment features are not installed. Withholding portal pages also avoid showing a misleading "Paid" label when payment features are present, keeping customer-facing information clearer.
Original PR description
When installing l10n_ec_edi with --skip-auto-install we receive an error on Runbot. Anchored on the sidebar title (always present on account.portal_invoice_page) rather than div[name='invoice_paid_badge'], which only exists when account_payment (not a dependency of this module) is installed and inherits this view to add it. Hides the account_payment "Paid" badge, if present, without requiring it to exist. runbot-237864 Forward-Port-Of: odoo/enterprise#129291 Forward-Port-Of: odoo/enterprise#126918
The Turkish reports journal form now places the return from sales account field in the correct position. This prevents labels and values from appearing under the wrong captions, making account setup clearer for users.
Original PR description
The journal form renders `default_account_id` as six standalone labels followed by two `nolabel="1"` fields, one for bank, cash and credit journals and one for sale, purchase and general ones. The xpath matched the first of those two fields, so the return from sales account was inserted between them. Its own label then landed in the middle of the label run, shifting the group grid: both labels rendered side by side with their values underneath, each next to the wrong caption. Anchor on the second field instead, so the new field follows the whole label and field run. Task-6438412 Forward-Port-Of: odoo/enterprise#129362 Forward-Port-Of: odoo/enterprise#128083
Invoice responses for French PDP invoices are now sent through only the PDP channel instead of both PDP and classic Peppol. This avoids duplicate response messages and reduces unnecessary clutter in invoice communications.
Original PR description
When responding to an invoice received through PDP, 2 responses were actually sent: one through PDP and the other through the 'classic' Peppol. This was done to allow more reliability, in case one channel is down when trying to respond, but this mainly creates cluttah' in the chattah' (call me busta rhymes yo) task-6522652 Forward-Port-Of: odoo/odoo#285596
The web test system now stops and reports a clear failure when required test dependencies cannot be loaded. This prevents build jobs from sitting idle until a timeout, helping teams identify infrastructure or setup problems faster.
Original PR description
Before this commit, a unit test suite could go silent between two test files, and `browser_js` then waited out its whole timeout before failing with:
[ERROR] TypeError: Failed to fetch
at orm (web.assets_unit_tests.min.js)
FAIL: WebSuite.test_unit_desktop
AssertionError: Script timeout exceeded
This happens because `fetchDependencies` gives every addon a `Deferred` that only the success handler of the batched `all_dependencies` call resolves, and a loaded runbot host answers that call with `RuntimeError: can't start new thread`. Nothing then settles those deferreds, so the `Promise.all` waiting on them never returns, `stop()` is never called, and the browser holds the build until the timeout.
This commit rejects the deferreds of a failed batch and reports an error escaping `runTests` on the console, so the build fails on the fetch error instead of running out its timeout.
https://runbot.odoo.com/odoo/error/243504
Forward-Port-Of: odoo/odoo#284980This fixes a timing issue in the QFPay point-of-sale refund flow that could start refunds too early and cause errors in automated checks. The update helps ensure refunded items are linked correctly and improves reliability across different module setups.
Original PR description
Due to the tour not waiting to click next order on the feedback screen, the refund was initiated too early causing the refunded line to not link properly. This resulted in multiple runbot errors depending on the installed modules. This commit fixes both the traceback by adding a conditional access, and the tour logic by adding a `clickNextOrder` step. runbot-939616, runbot-237992 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents slow simulated taps on touch devices from being mistaken for long presses during automated tests. It reduces random mobile test failures, helping keep validation runs more stable without changing business workflows.
Original PR description
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the…
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the write:
[verifySteps] expected the following steps
> Expected: [
"web_save",
]
> Received: []
This happens because a tap held longer than `LONG_TAP_DELAY` counts as a long press, and `_pointerUp` then dispatches no click at all. That delay spans the synthetic pointerdown and pointerup of a single `click()`, so the work a listener does during the press counts towards that delay: tapping save blurs the html field, which converts the whole editor content to inline styles, and under the load of a runbot build that conversion alone takes longer than the delay.
One solution could have been to raise `LONG_TAP_DELAY`, but a listener slower than the new value suppresses the click again.
This commit counts a tap as long only when the test releases the pointer itself, with `pointerUp`, so the work a listener does during a `click()` no longer suppresses the click.
https://runbot.odoo.com/odoo/error/946581
Forward-Port-Of: odoo/odoo#285640
Forward-Port-Of: odoo/odoo#284971This update makes an automated restaurant appointment test wait for a cancellation dialog to fully close before finishing. It helps prevent occasional false test failures, supporting smoother maintenance and more reliable releases without changing user-facing behavior.
Original PR description
Following commit b6a7991a6aaef1be15a27852c2c76737322cdcab, the tour clicks the cancel button (.o_form_button_cancel) to discard unsaved changes. However, as it was the last step of the tour, the test could terminate before the asynchronous discard/dialog closure completed. This caused intermittent test failures with: `AssertionError: Tour finished with a dirty form view being open.` We now add a final step that waits for the dialog to close and the form to no longer be marked as dirty (`body:not(:has(.o_dialog)):not(:has(.o_form_dirty))`) before completing the tour. Forward-Port-Of: odoo/enterprise#129375
This fix prevents an error when users close the email composer after selecting more than 500 CRM leads. It ensures the system can still identify the selected records without relying on a field that is intentionally left empty for large selections, improving reliability during bulk email workflows.
Original PR description
Steps to reproduce: 1. Install `crm` 2. Create leads more than 500. 3. Select all and try to send email 4. Not close the wizard by "X" Issue: - Traceback occurs: `Uncaught Promise > Unexpected end of JSON input` Cause: - res_ids is not set on the composer when more than 500 records are selected. This is expected, as the compute method `_compute_res_ids()` does not write `res_ids` when the number of `active_ids` exceeds 500 (to avoid storing large payloads on the field). Because of this, the code trying to JSON.parse(res_ids) fails while dismissing the wizard at `onCloseWizardModal` Solution: - Fallback to context.active_ids when res_ids is not available opw-5891862 Forward-Port-Of: odoo/odoo#252670 Forward-Port-Of: odoo/odoo#248406
A mail test helper now stops retrying after a timeout or failure instead of continuing to report the same failure during later test runs. This makes automated test results more reliable and easier for developers to diagnose, without changing customer-facing behavior.
Original PR description
Before this commit, one test contains() reaching its 10 seconds budget made the 129 tests that ran after it fail with its own assertion, over 14 suites:
[HOOT] Test "@mail/message/link_preview/Delete all link previews at
once" failed:
Failed assertion:
3. [toBe] expected values to be strictly equal (Failed to find 1 of ".o-mail-Message-body:text(...)" (Timeout of 87 seconds). Found 0 instead.)
This happens because the tick re-schedules itself on the result of runOnce(), which is undefined on a failure, the crashing one included. The check keeps selecting every 500ms and logs its assertion against whichever test is running, until a tick lands between two suites and getFixture() throws.
This commit re-schedules a tick only while the check is not done, so the crashing one is the last.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285585This change prevents automated test runs from recording an extra, misleading error after a failed web test suite. It keeps the memory information in the logs but records it before the final test result, making build failures clearer and easier to diagnose.
Original PR description
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one: odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser: Error received after…
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one:
odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser:
Error received after termination: [MEMINFO] tests done (after GC)
- used: 220535896 - total: 341990868 - limit: 4395630592
Note that the figures themselves are fine (220MB used of a 4.4GB limit): the error is not about memory, only about when the line is logged.
This happens because the runner logs that line after `stop()`, and `stop()` is what reports the suite result: the server settles the test on that report and kills the browser. The final major GC outlasts the report. A passing build escapes because the browser dies within milliseconds; a failing one stays up for the screenshot, long enough for the GC to finish and the line to land after termination.
This commit fixes the issue by moving `stop()` after the final cleanups and their memory log: the [MEMINFO] line is still logged, but before the result report, while the server still waits on the browser.
https://runbot.odoo.com/odoo/error/229655
Forward-Port-Of: odoo/odoo#284957This fix updates a mail test so emoji suggestions are closed before posting a message. It helps keep automated checks reliable without changing the user-facing messaging experience.
Original PR description
Before this commit, "[text composer] Posting message should transform relevant data to emoji." posted no message on runbot:
Failed to find 1 of ".o-mail-Message-body:text('test ...')"
(Timeout of 10 seconds). Found 0 instead.
This happens because "test :P :laughing:" leaves the emoji suggestion of the shortcode it just typed pending, and Composer.onKeydown returns without posting when the NavigableList takes the Enter. The fetch behind that suggestion is debounced by 250ms, so the test posts only while the debounce has not fired.
This comes from "[IMP] web,*: emoji loader": the search reads the emoji data the mail test helpers preload, so the list has an entry to offer where it had none.
This commit types a trailing space, which closes the suggestion and leaves the Enter to post.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285616The website shop now targets product option fields more precisely, preventing unrelated inputs from being affected. This helps avoid incorrect behavior on product pages and keeps the checkout experience more reliable for customers.
Original PR description
The selector was matching unrelated inputs because it wasn't specific enough. Forward-Port-Of: odoo/odoo#283742 Forward-Port-Of: odoo/odoo#283464
Manufacturing bills of materials now exclude combo products from component selection. This prevents configurable sales bundles from being treated as physical parts, reducing setup mistakes in production planning.
Original PR description
Version: --------- - 19.0+ Steps to reproduce: ------------------- - Install `mrp` and `sale_management` - Create a product of type `combo` - Go to Manufacturing > Products > Bills of Materials - Create or edit a BoM - Add a component line - Select the combo product Issue: ------ Combo products can be selected as BoM components. Since combo products represent configurable sales bundles rather than physical products, they are not meaningful manufacturing components. Before Commit: ------------------- - It was possible to select a product of type 'combo' as a component in a Bill of Materials. After Commit: ----------------- - Combo products are filtered out of the component picker and cannot be added as BoM components --- opw-6425024 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278861
This update fixes a forum test so it uses the intended helper forum and checks the correct karma requirement for commenting on someone else's post or reply. It helps ensure forum access rules are validated accurately, reducing the risk of permission-related regressions.
Original PR description
**Issue:**
`website_helpdesk_forum` overrides the `ref('website_forum.forum_help')` in its demo data, allowing anyone to comment / post on it.
**Fix:**
Use the helper forum instead and properly requires `KARMA['com_all']` when posting a comment on someone else post/reply.
related: https://github.com/odoo/odoo/commit/ba19ef413e400a65e9f43a6fc6c4bc1586ea8983
runbot-944703
Forward-Port-Of: odoo/odoo#285465
Forward-Port-Of: odoo/odoo#281757Event agenda pages with many items now scroll more smoothly in Firefox and Safari. This prevents the horizontal agenda view from shaking or jumping, improving the experience for visitors browsing event schedules.
Original PR description
On Firefox and Safari, horizontal scrolling on an agenda with many items stuttered. This was likely caused by triggering too many scroll events, without throttling them. Steps to reproduce: - On Firefox or Safari, run with demo data - Go to the "Design Fair Los Angeles" agenda (click on the event > Talks > Agenda. Alternatively, enter the URL directly: `/event/ID/agenda`, with the right event ID) - Resize the page (or open the dev tools) so that there is a horizontal scrollbar. - Scroll horizontally with a trackpad or with shift + mouse wheel. => The agenda stutters/shakes: as you go to the right, it sometimes slightly goes back left, and vice-versa. You might have to scroll from left to right and right to left a few times to see the issue. Forward-Port-Of: odoo/odoo#285237
Product variant prices now inherit the same minimum decimal display settings as their product template prices. This prevents prices such as 19.50 from appearing with too few decimals in Studio reports, improving consistency and reducing confusion.
Original PR description
Issue: --- Record's `min_display_digits` is not inherited in case of a model inheritance. e.g. `list_price` is inherited to `product.product` from `product.template`, however it renders with fewer decimals than `product.template.list_price` in reports. Steps to reproduce: 1- Set a product's Sales Price to 19.5. 2- Add `product.product.list_price` to a report using studio. The variant's field renders with 1 decimal while `decimal.precision` is 2. Cause: --- This is missed in ee32a17495a10af18f0b5de0a295283c5059d3c2 which introduces minimum precision. opw-6465159 Forward-Port-Of: odoo/odoo#285336 Forward-Port-Of: odoo/odoo#285064
The Kenyan e-invoicing form no longer shows an unnecessary blank gap when there is no validation message to display. This keeps the invoice screen cleaner and avoids visual confusion for users.
Original PR description
When there is no validation message, an empty div causes a whitespace gap between the header and the sheet in the form view. This commit adds `invisible="not l10n_ke_validation_message"` to the div to prevent this issue. Forward-Port-Of: odoo/enterprise#129364 Forward-Port-Of: odoo/enterprise#129318
The Indian Payroll settings now validate EPF employee IDs using the correct 15-character format. This prevents users from entering outdated or overly long identifiers and gives clearer guidance when configuring Employee Provident Fund details.
Original PR description
Steps to reproduce: - Install Indian localization, and use an Indian company - Go to Settings under Payroll > Indian Localization - Tick the "Employee Provident Fund (EPF)" - Insert a EPF Employee ID Issue: The "valid" format is not correct: XX/XXX/1234567/000/1234567 with the first series of 7 numbers having a flexible range from 1 to 7. The first series of 7 numbers must always equal to 7 (it represents the establishment ID), and the last series of number should be dropped as it represents the employee's unique PF account number. Solution: - Modify the constraint for the variable: - Remove last 7 trailing digits from the constraint. - Make the length of the first series of 7 digits strictly equal to 7. - Update placeholder value and help info. Task: 6482315 Forward-Port-Of: odoo/enterprise#128777 Forward-Port-Of: odoo/enterprise#128421
This fix prevents a warning from appearing during upgrades when employee records temporarily do not yet have version information. It helps keep upgrade logs cleaner and avoids unnecessary concern while the system completes its normal employee data backfill process.
Original PR description
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls…
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls back to `versions[0]` when no version matches the given date But if the employee has no versions at all, `versions` is empty and `versions[0]` raises an `IndexError` ### Steps to reproduce: - Create a database with `hr_attendance` installed in 18.0 - Upgrade to 19.0 Before the fix, a warning is logged during the upgrade ### Notes: An employee without any version is a transient state during upgrade `hr/saas~18.4.1.1/end-migrate.py` backfills a version for every employee still missing one (`current_version_id IS NULL`) once the whole upgrade chain is done Since it only runs at the very end, an employee can still be found without a version by earlier steps (e.g. modules reloading their demo data), which is when this warning was logged Confirmed on an upgraded RunBot database that employees without a version before the upgrade do end up with one once fully completed runbot-241187 Forward-Port-Of: odoo/odoo#284467
The Brazilian AvaTax Sales module now includes the missing dependency needed for its sales order fields to load correctly. This prevents installation failures when the module is installed manually with auto-install skipped, keeping Brazilian tax setup usable in affected deployments.
Original PR description
When installing l10n_br_avatax_sale with --skip-auto-install, you'll get an error about the l10n_br fields listed in views/sale_order_views.xml, because these fields don't fully exist without sale_external_tax. This happens because they're defined on a mixin, which is an abstract model. Abstract models only add their fields to a model that actually lists them in `_inherit`. sale.order should list this mixin, but currently doesn't. Adding that dependency is an unstable fix, so it will be added in master (20.0, or 20.1) runbot-237866 Forward-Port-Of: odoo/enterprise#128142
AvaTax invoice PDFs now align section or divider rows correctly when the Taxes column is hidden. This prevents misaligned borders and avoids large blank gaps on longer printed invoices, improving invoice presentation for customers.
Original PR description
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer…
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer invoice: - Use the customer with an AvaTax fiscal position and proper address details. - Add a product with an AvaTax category. - Add a section line (a divider/heading row). - Compute Taxes for the AvaTax. 4. Print the invoice as a PDF. 5. Look at the section/divider row. Its cell border does not line up with the other rows. On longer invoices, this can also cause a big blank gap at the bottom of a page. Cause: When an invoice is computed by AvaTax, the Taxes column is hidden from the PDF (this is intentional, since AvaTax shows tax differently). But a different part of the same template decides how wide the section row should be. This part does not know the Taxes column was hidden, so it still counts it. That makes the section row's width wrong by one column, which breaks the table layout in the PDF. Fix: Instead of hiding the Taxes column only in one place, fix it at the source: the variable that decides (does this invoice show a Taxes column) now also checks if the invoice is an AvaTax invoice. Every other part of the template that uses this variable (the header, the tax cells, and the section row width) automatically gets the right answer, since they all read from the same place. Result: - Section rows on AvaTax invoices now have the correct width. opw - 6455674 Forward-Port-Of: odoo/enterprise#129097
This fix updates how Odoo passes certificates and private keys to its secure connection setup so it works cleanly with newer operating system library versions. It prevents unnecessary warnings in automated checks and helps keep email and certificate-related connections stable across environments.
Original PR description
pyOpenSSL 24.3.0 deprecated passing its own X509/PKey objects to Context.use_certificate()/use_privatekey(), and started accepting cryptography objects instead. Odoo pins pyopenssl 24.1.0, but the distro builds run the version shipped by the OS: since the test added by f0fb287c6502 covers that path, they now add a warning in the logs. Load the certificate and the key as cryptography objects when the installed pyOpenSSL supports them, keep the previous loaders otherwise. Reference: https://github.com/pyca/pyopenssl/commit/b0cb4b4 This fix is based on https://github.com/odoo/odoo/blob/a2b4f618328f3ce3f654fd2c1ee4410365706a7e/odoo/addons/base/models/ir_mail_server.py#L34-L46 runbot-944176 Forward-Port-Of: odoo/odoo#285569 Forward-Port-Of: odoo/odoo#277449