Monday, September 21, 2026
31 changes · saas-19.3
Resolved issues and error corrections
New US companies using AvaTax will now get the correct tax accounts when accounting is set up without demo data. This prevents newly computed AvaTax taxes on invoices from missing their account assignment, reducing setup errors and accounting inconsistencies.
Original PR description
Steps to reproduce: - Create a DB and Install `Accounting` without demo data - In Companies > Create New Company with `US` Localization - Switch to US Company > Add `Avatax` Credentials - Create a…
Steps to reproduce: - Create a DB and Install `Accounting` without demo data - In Companies > Create New Company with `US` Localization - Switch to US Company > Add `Avatax` Credentials - Create a Product with `Avatax Category` - Create a Invoice > In Other Info `Fiscal Position` - `Automatic Tax Mapping (AvaTax)` > `Compute Taxes` - In Taxes check newly created tax does not have a account ID Issue: AvaTax fiscal position created from chart templates have empty `avatax_invoice_account_id` and `avatax_refund_account_id` fields on a fresh database without demo data. Problem: Both fields use [defaults] based on `company.account_sale_tax_id`. During initial CoA loading, `_load_data()` creates the AvaTax fiscal position before `_post_load_data()` sets `company.account_sale_tax_id`. The defaults therefore resolve to an empty recordset and no tax account is assigned. This issue does not occur in databases with demo data because the demo company is already loaded, so `company.account_sale_tax_id` is already set when the AvaTax fiscal position is created. Solution: Set the invoice and refund accounts explicitly in the AvaTax fiscal position template to ensure they are correctly assigned during CoA loading. [defaults]: https://github.com/odoo/enterprise/blob/de17c107651394025e9a3d5cbed8d81bcfc2e76d/account_avatax/models/account_fiscal_position.py#L9-L13 opw-6347128 Forward-Port-Of: odoo/enterprise#132005 Forward-Port-Of: odoo/enterprise#126604
The Source PO button now appears only on subcontractor resupply receipts that should link back to the subcontracted purchase order. This prevents unrelated purchase receipts from showing misleading purchase order links, helping users avoid confusion when managing subcontracting flows.
Original PR description
After a recent change, the smart button for Source POs uses the reference_ids on a stock.picking. This altered the logic to fetch all orders from any picking that has the same reference. However,…
After a recent change, the smart button for Source POs uses the reference_ids on a stock.picking. This altered the logic to fetch all orders from any picking that has the same reference. However, `subcontracting_source_purchase_count` should specifically relate to the resupply of subcontractor picking to their subcontracted purchase order. **Steps to Reproduce:** 1. Enable multi-step routes and subcontracting 2. Unarchive the MTO route 3. Create 4 products Finished Product, A, B, C, and set MTO on both A and B 4. Put 10 units of C in stock 5. Create a BoM for Finished Product using A and B as components 6. Create a subcontracted BoM for B using C as a component 7. Set the purchase vendor for product A as the vendor 8. Set the purchase vendor for product B as the subcontractor 9. Create and confirm a manufacturing order for Finished Product 10. Confirm the POs The two POs are: 1. Purchase Product A from its vendor 2. Subcontract Product B from its subcontractor and use Product C as a component **Current Functionality:** - Product A's receipt has a **Source PO** smart button pointing to the subcontracting PO for Product B (BUG) - Product B's receipt has a **Source PO** smart button pointing to its own PO (BUG) - Product C's picking has a **Source PO** smart button pointing to its own PO **New functionality:** - Product A's receipt has no **Source PO** smart button - Product B's receipt has no **Source PO** smart button - Product C's receipt has a **Source PO** smart button pointing to its own PO opw-6420168 Forward-Port-Of: odoo/odoo#278908
Fixes an error that could interrupt website setup when enabling an online store option. This helps users complete the configurator smoothly without being blocked by a server error during demo data loading.
Original PR description
Since [1], the registry is loaded without a request context, so a module installation now goes through the fallback of `get_current_website` that reads the url stored on the current thread. That…
Since [1], the registry is loaded without a request context, so a module installation now goes through the fallback of `get_current_website` that reads the url stored on the current thread. That value is a full url, not the `domain:port` the method expects, so IDNA-encoding it splits it on the dots of the path rather than on those of a host name and raises `UnicodeError` as soon as one of the resulting parts reaches 64 characters. The thread url is now reduced to its `domain:port` part. Steps to reproduce: - Start the server locally on a database with demo data, served on `http://localhost:8069`, with only `Website` installed - Create a new website - In the configurator, choose `I want an online store` - Go through each step - After the last step, a traceback appears while loading the accounting demo data: the configurator should apply without error [1]: https://github.com/odoo/odoo/commit/1ae80f9fb18c9c9e67fe0367b94f0d882c711570 Also reported here: https://github.com/odoo/odoo/issues/286432 Forward-Port-Of: odoo/odoo#288931
The accounting tests now use a proper PDF file instead of invalid sample content. This helps prevent false test failures and keeps quality checks stable without changing user-facing behavior.
Original PR description
Use PDF_RAW from base.tests.files instead of fake (and invalid) PDF content, like the other tests needing a PDF attachment. runbot-946577
This fix updates an automated inventory workflow test so it works correctly when the Turkish Nilvera e-Dispatch localization is installed. It prevents false test failures caused by a different screen identifier, helping keep stock operations validation reliable for localized deployments.
Original PR description
### Steps to reproduce: - Install `l10n_tr_nilvera_edispatch` (e.g. the `tr` country build) - Run `test_basic_stock_flow_with_minimal_access_rights` > The tour times out on step 6/31, "check that at…
### Steps to reproduce: - Install `l10n_tr_nilvera_edispatch` (e.g. the `tr` country build) - Run `test_basic_stock_flow_with_minimal_access_rights` > The tour times out on step 6/31, "check that at least one picking is present in the view". ### Cause of the issue: The step triggers on `.o_stock_list_view_view`, a class the web client derives from the `js_class` of `stock.vpicktree`: https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/stock/views/stock_picking_views.xml#L66-L70 https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/web/static/src/views/utils.js#L45-L68 `l10n_tr_nilvera_edispatch` overwrites that attribute to plug in its e-Receipt upload button, so the root carries `o_l10n_tr_edispatch_tree_view` instead and the trigger never matches: https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/l10n_tr_nilvera_edispatch/views/stock_picking_views.xml#L4-L13 Only the class name changes: `L10nTrNilveraEdispatchListView` spreads `StockListView`, so the rendered list is identical. runbot-947260 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288404 Forward-Port-Of: odoo/odoo#288255
The system now blocks creation of API keys that are already expired. This helps prevent mistakes when users copy example settings or enter past dates, reducing confusion and avoiding unusable keys.
Original PR description
Prevent creating API keys that are already expired. One typical case is when you copy/paste the documentation and end up creating keys that are already expired, without noticing. Forward-Port-Of: odoo/odoo#288154 Forward-Port-Of: odoo/odoo#286548
Sales credit limit checks now count confirmed customer orders even when products have not yet been delivered. This helps businesses spot customers who are already over their limit before accepting more orders, reducing credit exposure.
Original PR description
### Steps to reproduce Set a credit limit of 1.000 on a customer, then: 1. Create a Sale Order for a product with Invoice Policy on **Delivered Quantities**, over that amount → the warning shows.…
### Steps to reproduce
Set a credit limit of 1.000 on a customer, then:
1. Create a Sale Order for a product with Invoice Policy on **Delivered Quantities**, over that amount → the warning shows. Good.
2. Confirm it, and deliver nothing.
3. Create a second order for the same customer → the warning never shows, even though the customer is already over the limit.
### Solution
The ordered quantity is what the customer committed to, delivered or not. Using `qty_to_invoice` instead of `uom_qty_to_consider` or `qty_delivered`
Introducing invoice_status in sales domain for `_compute_credit_to_invoice`: `untaxed_amount_to_invoice` still follows the invoicing policy, while `amount_to_invoice` no longer does. On a confirmed order for a delivery-based product with nothing delivered:
```
line.untaxed_amount_to_invoice = 0 # still gated by qty_delivered
line.invoice_status = 'no'
order.amount_to_invoice = 2000 # fixed by this PR
```
The domain filters on the first one, so the order is dropped from the search before its amount is ever read and `credit_to_invoice` stays at 0.`'no'` is the stored marker for a confirmed line that is not invoiceable yet, which is exactly what the first clause misses.
ticket: [6480211](https://www.odoo.com/odoo/project/967/tasks/6480211)
Forward-Port-Of: odoo/odoo#288659
Forward-Port-Of: odoo/odoo#285578The calendar view now switches properly between desktop and mobile filter panels when the browser window is resized. This prevents the calendar legend panel from staying open by default on smaller screens, improving usability for mobile users.
Original PR description
See commits Forward-Port-Of: odoo/odoo#289203 Forward-Port-Of: odoo/odoo#288329
This fixes an issue where installing Chilean localization demo data alongside other localizations could fail and leave the Chilean demo company without accounting examples. The change ensures only suitable Chilean demo transactions are posted, improving setup reliability for demo and testing environments.
Original PR description
When several localization modules are installed at once (with demo data), loading the chilean demo data fails and the chilean demo company ends up without any accounting demo data. Steps to reproduce: - Install `l10n_cl` together with the other localizations and the enterprise addons, with demo data enabled Issue: Error while loading accounting demo data ValidationError: Document types for foreign customers must be export type (codes 110, 111 or 112) or you should define the customer as an end consumer and use receipts (codes 39 or 41) Analysis: Demo methods will posts every move of the chilean company, not only the ones prepared by the module. In combination with other modules loading their own demo data it may raise the said error. Forward-Port-Of: odoo/odoo#288590
Malaysia payroll calculations now use the correct SOCSO Act 800/EIS treatment and avoid double-counting employee SOCSO deductions. This produces more accurate net pay and clearer employer contribution reporting on payslips.
Original PR description
There was a difference between the actual and expected NET. **Causes** - rules existed for both SOCSO Act 800 and EIS, but Act 800 seems to be the official name of the Employment Insurance System…
There was a difference between the actual and expected NET. **Causes** - rules existed for both SOCSO Act 800 and EIS, but Act 800 seems to be the official name of the Employment Insurance System (source: https://www.perkeso.gov.my/images/dokumen/Rate_of_Contribution_ACT_800.pdf). Keep the ACT 800 one as its matches the expected amount. - there was a double counting of the SOCSO employee contributions (4 and 800) , as `l10n_my_rule_socso_employee` (the sum of both) was added to the total deductions. **Change** Before: 3500/month wage results in a 3108 NET. <img width="1181" height="533" alt="before" src="https://github.com/user-attachments/assets/cdf4420f-e2cf-4dc7-9488-6bde3f1f9961" /> After: 3500/month wage results in a 3090.85 NET: - 6.90 SOCSO Act 800 Employee - 6.90 SOCSO Act 800 Employer - 17.25 SOCSO Act 4 Employee - 60.35 SOCSO Act 4 Employer Which seems consistent with online sources (https://payroll.my/) <img width="1181" height="425" alt="after" src="https://github.com/user-attachments/assets/7fb41186-dbb4-4d7a-ac9a-14fb56efc4bc" /> Other fix: while not affecting the calculation, 'SOCSO Employer Share' appeared as incorrect, the two rules SOCSO_800_EMPLR and SOCSO_4_EMPLR should have the same sign. opw-5976362 Forward-Port-Of: odoo/enterprise#131023 Forward-Port-Of: odoo/enterprise#118138
Moved documents now correctly inherit group access permissions from their destination folder, even when that folder has no owner. This prevents authorized group members from unexpectedly losing access after files are dragged or moved into shared folders.
Original PR description
When moving a document into a folder (e.g., via drag and drop), the document fails to inherit the group access rights defined on the destination folder if that folder does not have an owner. While direct uploads correctly apply the groups, moved documents only inherit partner access rights in this scenario, potentially leaving group members without the expected access. This occurs because group access rules were inadvertently filtered out during the rights sync when the system evaluated the missing folder owner. This commit ensures that group-based access rules are correctly retained and applied to the document when it is moved into a folder, regardless of whether the destination folder has an owner. Steps to reproduce: - Create a new folder and ensure the "Owner" field is empty. - Add a group to the folder's access rights. - Drag and drop a file from elsewhere into that folder. - Notice the document doesn't inherit the group from the parent folder. Task-6585315
Changing the delivery address on an outgoing rental transfer no longer resets the destination from the rental location to the customer's standard location. This prevents rental orders from being routed incorrectly and keeps rental inventory movements accurate.
Original PR description
**Issue** Changing the `partner_id` of an outgoing rental transfer could reset its destination location to the partner customer location instead of the rental location. **Steps to reproduce** -…
**Issue** Changing the `partner_id` of an outgoing rental transfer could reset its destination location to the partner customer location instead of the rental location. **Steps to reproduce** - Enable Rental Transfers from Rental Configuration. - Create a Sales Order for a rental product. - Open the related delivery transfer. - Using Studio, make the Destination Location field visible. -> Current destination location is: Partner/Customer/Rental - Change the delivery address -> The destination location become: Partner/Customer **Cause** Changing the delivery address (i.e: the partner_id) triggers `_compute_location_id`: https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L949-L950 Since commit https://github.com/odoo/odoo/commit/8c90fc1fd336ee872fd67d8d72473e4f6c55b2e0, not only draft picking are recomputed. As a result, `location_dest_id` is set as `picking.partner_id.property_stock_customer` https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L959-L961 https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L963 Regardless whether we are in rental setup opw-6237495 Forward-Port-Of: odoo/enterprise#126158 Forward-Port-Of: odoo/enterprise#123564
Helpdesk teams can now link to multiple community forums without the website page crashing. This ensures customers can reach the correct forum listing from the Helpdesk website flow, including when eLearning forum features are installed.
Original PR description
### Steps to Reproduce: 1) Install `website_helpdesk_slides_forum` module 2) On a Helpdesk team, link 2 (or more) forums under `Commnity Forums`. 3) Click on website smart button and then click `Ask…
### Steps to Reproduce: 1) Install `website_helpdesk_slides_forum` module 2) On a Helpdesk team, link 2 (or more) forums under `Commnity Forums`. 3) Click on website smart button and then click `Ask the community` button. ### Error: ``` odoo.addons.base.models.ir_qweb.QWebException: Error while render the template KeyError: '_forums' Template: website_helpdesk_slides_forum.helpdesk_forums ``` ### Root Cause: https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_forum/controllers/website_forum.py#L18-L22 On clicking the "Ask the Community" button calls the `helpdesk_forums` controller. A single forum redirects straight to it. Several forums get rendered through `get_template_xml_id()`, with only `forums` in context. `get_template_xml_id()` is overridden in `WebsiteSlidesForumHelpdesk`, which points to : https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_slides_forum/views/helpdesk_templates.xml#L3-L5 a primary copy of the inner partial `forum_all_all_entries`. That partial needs `_forums` (and, once extended by website_slides_forum, courses_discussions too), both only ever set by the page template's own t-call: [Reference](https://github.com/odoo/odoo/blob/23af2b443735c6d3a2f64e44f9ea5da45638b052/addons/website_forum/views/forum_forum_templates_forum_all.xml#L18-L19) Since `helpdesk_forums` is rendered directly instead of going through `website_forum.forum_all`, `_forums` is never set, hence `KeyError` occurs. The base `website_helpdesk_forum` module has the same root cause one level up, surfacing as a different error: https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_forum/controllers/website_forum.py#L24-L25 `website_helpdesk_forum.forum_all` does not exist anywhere in the codebase. A team with multiple forums, without `website_helpdesk_slides_forum` installed, hits ``` ValueError: View 'website_helpdesk_forum.forum_all' in website 1 not found ``` Instead of a listing page. ### Fix: - Both `get_template_xml_id()` implementations now return the real, working `website_forum.forum_all` page template, which already sets `_forums/courses_discussions` through its own `t-call` and wraps the result in website.layout. - `helpdesk_forums()`'s render values are now built through an overridable `_get_helpdesk_forums_render_values()` hook instead of a hardcoded dict, so subclasses can extend the context. - `website_helpdesk_slides_forum` uses that hook to set `hide_forum_slides_link=True`, and adds one small non-primary view inheriting `website_slides_forum.forum_all_all_entries` that conditions the `/slides` promo link (not the "Course" badge, which doesn't navigate anywhere) on `not` `hide_forum_slides_link`. This targets the link element itself rather than a `t-call` site in `forum_all`, so it correctly applies whether `website_slides_forum` groups a given forum as "regular" or "course-linked". **opw-6332175** Forward-Port-Of: odoo/enterprise#131734 Forward-Port-Of: odoo/enterprise#124104
Employees without HR access can now see one-off work location entries in the calendar, matching the visibility of recurring work locations. This fixes an inconsistency that could hide important availability or location information from colleagues planning meetings or schedules.
Original PR description
**Steps to reproduce** - With a user having HR rights, create an exceptional work location for a user (click on the top bar of one of the days in the calendar, where work locations are displayed, and do not check "repeat every". - Open the calendar app with a user having no HR rights, in the sidebar, add the user with a non-recurrent work location. Notice that the work location is not visible, unlike recurring ones. **Cause** Recurring work locations are defined on the public employee (`*_location_id` type fields) and are readable by all users. Non-recurring work locations are `hr.employee.location` records and the `homeworking_own_rule` rule restricts read operations for non-HR users. opw-6190464 Forward-Port-Of: odoo/odoo#266380
FIFO component costs are now calculated using stock movements from the correct company only. This prevents manufacturing costs in one company from being incorrectly based on purchases made by another company, improving financial accuracy in multi-company setups.
Original PR description
**Problem**: In a multi-company environment, while manufacturing a product, if the component of the product is visible for both company and there is no last_in stock move for the component in the current company, then the last_in stock move of the other company is used to compute the cost of the component. This only happens when the costing method of the product is FIFO **Steps to reproduce:** 1. Create company A and company B. 1. Create a product A and set FIFO costing method to it. 2. Make a purchase order of product A in company A and receive it. 3. Create a product B with product A as its BOM material. 4. Create a MO of product B in company B and produce it. 5. The unit cost of product A in company B is using the unit cost from the purchase order of product A in company A. **Fix**: Add a company domain to the last_in stock move search to prevent cross-company last_in stock move search. opw-6411216 Forward-Port-Of: odoo/odoo#280074
Managers with Time Off approval rights can now approve employee leave requests even when the leave overlaps with a paid payslip. This prevents approval work from being blocked by payroll-only access restrictions, reducing delays for HR and team managers.
Original PR description
### Steps to reproduce: - Create two employees: Employee A (Manager) and Employee B (Employee subordinate to A) - Create a user for Employee A and grant Time Off approval rights, but no Payroll…
### Steps to reproduce: - Create two employees: Employee A (Manager) and Employee B (Employee subordinate to A) - Create a user for Employee A and grant Time Off approval rights, but no Payroll access - Create a payslip for Employee B for the current month - Validate and mark the payslip as Paid - Log in as Employee B and submit a Time Off request for the current month - Log in as Employee A and open Employee B's Time Off request to approve it > AccessError: You do not have enough rights to access the field "payslip_state" on Time Off (hr.leave). Please contact your system administrator. ### Cause of Issue: When a leave overlaps with a validated payslip and no waiting payslip is found, the `hr_payroll` override of `_action_validate()` attempts to set the leave's `payslip_state` to `blocked`. However, the `payslip_state` field is restricted to users with Payroll access (`hr_payroll.group_hr_payroll_user`). Because the manager approving the leave only has Time Off approval rights, the write operation fails with an access rights error. ### Fix: Use `sudo()` to bypass the AccessError, since it's the common approach in this module opw-6501386 Forward-Port-Of: odoo/enterprise#129880
This fixes an issue where a child contact could show an incorrect VAT validation result when processed before its parent company. Parent companies are now checked first, so related contacts inherit the correct VAT status and business records stay accurate.
Original PR description
**Description of the issue/feature this PR addresses:** When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to…
**Description of the issue/feature this PR addresses:**
When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to be iterated before its parent, the child ends up with `vies_valid=False` instead of the parent's real, freshly-checked value.
**Current behavior before PR:**
`_compute_vies_valid` loops over `self` in whatever order the batch happens to have:
```python
for partner in self:
...
if partner.parent_id and partner.parent_id.vies_vat_to_check == partner.vies_vat_to_check:
partner.vies_valid = partner.parent_id.vies_valid
continue
status = partner._check_vies_iap()
partner._update_vies_status(status)
```
`Field.compute_value()` removes the whole batch from the "to compute" queue *before* running this loop (it does so upfront, in case the method does not assign every record). So when the loop reaches a child and reads `partner.parent_id.vies_valid` to reuse it, that field is no longer marked "to compute" for the parent, and reading it just returns whatever is currently cached/stored — which, if the parent has not been processed yet in this same loop, is still the old/default value. The child copies that stale value and, being a stored field, keeps it forever: nothing re-triggers its computation afterwards.
Example:
```python
parent = env['res.partner'].create({'name': 'Parent Co'})
child = env['res.partner'].create({'name': 'Child Address', 'parent_id': parent.id})
child.vat = 'BE0477472701' # queues the child's compute first
parent.vat = 'BE0477472701' # queues the parent's compute second
child.vies_valid # False, even though the VAT is valid
parent.vies_valid # True
```
**Desired behavior after PR is merged:**
Every partner without a parent is always computed before any child that may reuse its value, regardless of the batch's original order — so the child correctly ends up with the parent's real `vies_valid`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287351
Forward-Port-Of: odoo/odoo#279927Fixed an accounting issue where certain vendor payments could be marked as paid while their related batch payment remained stuck as sent. This keeps payment and batch statuses aligned, reducing manual follow-up and confusion in payment processing.
Original PR description
A payment on a journal without outstanding account has no journal entry, so it is matched as soon as it is paid. When the bill it pays is reconciled later on, _compute_state turns it to 'paid', but assigning a field from within a compute doesn't notify the fields depending on it: is_matched stays False and any batch payment holding that payment stays in 'sent' state. Mark is_matched for recomputation explicitly, as 18.0 already does since d8de234. Steps to reproduce: - On the Bank journal, leave the outstanding account empty on the outbound payment method line - Post a vendor bill - Register a payment on it - Put that payment in a batch payment and validate the batch - Create a MISC entry and reconcile the bill with it - Issue: bill and payment are 'Paid' but the batch stays 'Sent'. Forward-Port-Of: odoo/odoo#288981 Forward-Port-Of: odoo/odoo#288460
This fix ensures purchase order email templates are properly updated during upgrades instead of being skipped. It prevents an error when users edit only the unit price on a confirmed purchase order in migrated databases.
Original PR description
In this commit: eadf127 the `track_po_line_template` template was added in a `noupdate` file. The commit specifies: “put their declaration in no update when not done if template has no technical code or complex dependency on underlying code;” However, this is not actually the case for the two templates in this file. This did not cause any error in v17, but errors started appearing later because of #254602, which modified this code and the related Python code, leading to an error when no product quantity is changed. Steps to reproduce in a 19.3 database migrated from v19: - Create a purchase order with one product line and confirm it. - Only change the unit price of that line. - Error: "Error rendering template: ..." While this can also be considered a migration issue, I think the simpler and more logical solution is to remove the noupdate from this file. opw-6518729 Forward-Port-Of: odoo/odoo#288463
This fix improves French PDP e-invoicing logs when an unsupported lifecycle status is received. Instead of showing a blank or unhelpful value, the system records the actual status code, making troubleshooting easier for support teams.
Original PR description
Currently we just log `None` in case we receive a lifecycle with an unsupported (on community side) status. After this commit we log the status code at least. task-None before fix <img width="711" height="120" alt="image" src="https://github.com/user-attachments/assets/1f939cf4-17b7-49cb-8b31-5cc594fdeadd" /> after fix <img width="700" height="116" alt="image" src="https://github.com/user-attachments/assets/1b8b3853-f2da-4426-9c49-1d135d1c7824" /> Forward-Port-Of: odoo/odoo#286429
This fixes an issue in the website HTML builder where using arrow keys to adjust certain size or slider number fields only changed the preview temporarily. The updated value is now properly saved, preventing settings from reverting after the user clicks away.
Original PR description
When a BuilderRange is displayed with its optional number input, using ArrowUp/ArrowDown updates the preview but does not save the new value. The range component passes its handler through onKeydown, while BuilderNumberInputBase only calls onKeydownArrow after handling arrow keys. As a result, the debounced commit is skipped. Steps to reproduce: - Drop a s_social_media inner snippet - Click on the snippet, then click on the "Size" input - Use "ArrowUp" to increase the value of the number input - Click anywhere on the page => The size goes back to the previous one. task-6385984 Forward-Port-Of: odoo/odoo#283504
This fixes a manufacturing test that could fail depending on the timezone of the system running it. The change makes automated checks more consistent and reduces false failures during quality validation, without changing user-facing behavior.
Original PR description
**PROBLEM**
In `test_generate_serial_button_sequence()` we generate a serial number based on the day of the year. In ir_sequence, we use the time based on the environment timezone, but in the test, we don't use any timezone. This can lead the assertion to fail, since the day of the year can differ with the timezone used.
**REPRO STEPS**
1. edit the freeze_time in the test to `freeze_time('2024-01-15T23:00:00')`
If your timezone is UTC+2, then the time according to your timezone will be `2024-01-16T01:00:00`
So, without in UTC+0, it's the 15th day of the year, but in UTC+2 it's already the 16th.
Remove the timezone in the last assertIn() (ie, remove the fix).
(if your timezone is different, adjust the freeze_time accordingly)
2. run the test and see it fails.
runbot-237780
Forward-Port-Of: odoo/odoo#285647This fix prevents the mobile cart summary from covering address fields when shoppers use the on-screen keyboard on Android. It makes checkout easier to complete on mobile devices and reduces friction for guest customers entering delivery details.
Original PR description
The mobile summary element hides the address form on Android Steps to reproduce: 1. Install eCommerce 2. On android (or using browserstack) and without being logged in, go to the eCommerce 3. Add any…
The mobile summary element hides the address form on Android Steps to reproduce: 1. Install eCommerce 2. On android (or using browserstack) and without being logged in, go to the eCommerce 3. Add any product to the cart and go to checkout 4. Click on "Checkout" to enter the address details 5. Open the keyboard by clicking inside the first input 6. The virtual keyboard opens, enter a name and click on "Next" in the virtual keyboard 7. Do this a couple of times: the cart summary element doesn't scroll and the input field is hidden behind it Similar problem happens when you scroll a bit after clicking in the first input: the cart summary element displayed at the bottom is still visible (on top of the virtual keyboard) which hides part of the page and makes it difficult to navigate the page and fill in the details Issue: `sticky-bottom` keeps the element at the bottom of the screen Solution: Remove class `sticky-bottom` from `o_mobile_summary` when we click in one of the input opw-6500503 Forward-Port-Of: odoo/odoo#287464
This fixes a cart update issue that could make the rental date picker stop responding after customers used quick reorder from the cart. The cart summary now refreshes without disrupting the page element behind it, preserving a smooth checkout experience for rental products.
Original PR description
`updateCartSummary` refreshes `o_wsale_shorter_cart_summary` via `replaceWith`, detaching the node and inserting a new one. `reorderProduct` in quick_reorder.js ends up restarting an interaction on the previous node instead of the new one. For rental products, this leaves the daterange picker rendered but inert after a quick reorder from the cart. This commit updates the existing node instead of replacing it, so its identity is preserved. Issue present since PR: https://github.com/odoo/odoo/pull/234965 Forward-Port-Of: odoo/odoo#288559
Safari users can now replace selected text at the start of an editable note without losing the typed character. This prevents a frustrating editing issue where selected content was deleted but the replacement letter did not appear.
Original PR description
When using Safari, if the first character of the editable is selected and a character is pressed, the selection content is removed, but the character is not inserted. It seems that Safari does not trigger the actual `input` event, nor its native behavior, if the initial anchor node is detached from the DOM after `beforeinput`. This commit avoids this issue by preventing Safari from proceeding with the insertion right after the deletion by instead re-triggering the `insertText` command. Steps to reproduce: - Use Safari - Go to a To do note - Select the first word - Press a letter => The first word was deleted but the letter was not inserted. task-6445669 Forward-Port-Of: odoo/odoo#288848 Forward-Port-Of: odoo/odoo#281223
Fixes the Colombian Libro Diario report so comparison views no longer crash and journal entries without a partner are included as legally required. The report also keeps partner and label headers visible when those values are blank, improving completeness and reliability for compliance reporting.
Original PR description
## [FIX] l10n_co_reports: fix UNION ALL crash with multiple column groups ### Issue: Any comparison mode (Period, Analytic, etc.) in the Libro Diario raises an Odoo Server Error ### Cause: Each…
## [FIX] l10n_co_reports: fix UNION ALL crash with multiple column groups
### Issue:
Any comparison mode (Period, Analytic, etc.) in the Libro Diario raises an Odoo Server Error
### Cause:
Each sub-query in the `UNION ALL` had its own `ORDER BY` SQL only allows one global `ORDER BY` on a `UNION ALL`, or parentheses around each query — neither was the case
### Steps to reproduce:
- Install `l10n_co_reports` and `accountant`
- Enable Developer Mode in Settings
- Open the Libro Diario report and click the gear icon (top right)
- In the Options tab, enable Period Comparison
- Enable the Comparison for the Previous Period
Before the fix, an error is raised
------------------------------
## [FIX] l10n_co_reports: include partnerless entries in Libro Diario
### Issue:
Journal entries without a partner are excluded from the report but are legally required to appear
### Cause:
`_get_domain` called `super()` which adds `('partner_id', '!=', False)` to the domain, filtering out all partnerless entries
The SQL query also used a `JOIN` instead of `LEFT JOIN` on `res_partner`, excluding lines with no partner at the DB level
### Notes:
`NULL` values for `partner_name` or `line_label` caused the JS to hide the corresponding column headers
`header.js` matches columns to their header by `column_group_index`/`expression_label` and skips `None` values
Fixed by using `COALESCE` to return an empty string instead
### Steps to reproduce:
- Install `l10n_co_reports` and `accountant`
- Create a Journal Entry without a partner or label
- Open the Daily Journal Report
Before the fix, the entry doesn't appear
After the fix, check that PARTNER and LABEL headers are visible
opw-6430728
Forward-Port-Of: odoo/enterprise#132066
Forward-Port-Of: odoo/enterprise#129674Product option pills in the sales configurator now keep clear spacing when they wrap onto multiple lines. This improves readability and avoids a cramped layout for products with many attribute choices.
Original PR description
Pill-style attribute values used Bootstrap's list-inline/list-inline-item, which only sets margin-right between items. When pills wrapped onto a new line, the rows touched with no vertical gap. Fix: Switch the pill list to a flex container with gap-2, matching the spacing website_sale already uses for its own attribute-value lists, so wrapping rows get the same gap as pills on the same row. opw-6584507 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289176
Payroll dashboard warnings for starting a new or current payroll now respect a user's choice to hide or archive them. This prevents the same warning from repeatedly appearing after dismissal, reducing confusion for payroll users.
Original PR description
Issue: ---------------------------------------- The "Create New Payroll"/"Current Payroll" warning is always displayed, even when hiding or archiving it. Steps to reproduce: ---------------------------------------- - Go to the Payroll Dashboard - Click "Set Schedule" if the warning is there - Then a new warning appears: "Create New Payroll" - Try hiding it by clicking the cross (with or without "Never show it again") - The warning is always there Cause: ---------------------------------------- The warning is added through `_get_payrun_start_warning()` which ignores the `effective_domain`. It even ignores of the warning is active or not by getting it through its ref. Solution: ---------------------------------------- Only call `_get_payrun_start_warning()` if the warning matches the `effective_domain`. opw-6366294
Failed payment transactions that need manual intervention will no longer be retried automatically every few minutes, preventing repeated external API calls and unnecessary noise. Users are now informed on the related record when post-processing fails, making payment issues easier to notice and resolve.
Original PR description
[FIX] payment_transaction: stop post-processing cron from retrying persisting errors and sending repeated API calls Currently, when a transaction fails to process as part of the "Payment:…
[FIX] payment_transaction: stop post-processing cron from retrying persisting errors and sending repeated API calls Currently, when a transaction fails to process as part of the "Payment: Post-process transactions" cron, the transaction is retried with the next cron run, 10 minutes later. When the blocking error is a persisting one (such as for a UserError that cannot be resolved without manual intervention), the cron will retry repeatedly. The cron may send API calls as part of the process, resulting in hundreds of repeat API calls over the four days allotted for retrying. Additionally, we do not have a mechanism to notify the user that this process is failing outside of the server logs - the user does not know the record is failing, nor do they know why. Steps to reproduce: 1. Configure Avatax in the company's tax settings. 2. Set up a transaction that will fail during post-processing. Here is an example setup: -Enable superuser -Create new sale order draft for a user in company 1. -Set the user to company 2 -Confirm the sale order and make a payment -The payment should go through, creating a transaction -Run the post-processing cron, which should fail while processing the transaction. -Note the error in the server log, and note that the transaction's is_post_processed field stays "false" -Note the Avatax logs record an API call. -Run the post-processing cron again, noting the same log entry, is_post_processed = false, and another API call. Solution: This issue is only partially addressed in the current master branch: the four-day allotment is reduced to one day. However, it does not resolve any other issues, mainly that of re-processing records with persisting errors. Similar crons with API components (such as for Amazon and Peppol) already have mechanisms in place to prevent repeated retries for records with persisting errors. This should provide precedent for the following solution: 1. Logic to block records with persisting errors from being automatically retried. 2. A helper function that produces a chatter message in the related record. 3. A helper field to track post-processing errors and support the new logic. opw-6486459 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Creating an onsite event from the Onsite action now uses the current user's employee record when no specific employee is provided. This prevents an error and ensures the new event is visible in the expected kanban view.
Original PR description
The Onsite action only sets the hr_skills_event_add_employee key in its context, without any employee. Reading default_employee_id directly then raised a KeyError. Even before that, no attendee was added, so the new event did not match the domain of the action and stayed hidden in the kanban view. We now fall back on the employee of the current user. taskid-6361432 Forward-Port-Of: odoo/odoo#288241
A redundant internal step was removed from maintenance request creation. The maintenance team is already assigned automatically, so this cleanup has no impact on users or daily workflows.
Original PR description
The create method assigned request.maintenance_team_id to itself, a no-op that reads and writes the same value and has no effect. This line originally set the team from the equipment as a fallback when creating a request. PR #196181, while refactoring mail alias handling from equipment category to team, replaced that assignment with a self-assignment, turning it into dead code. maintenance_team_id is a required field and is already a stored compute depending on equipment_id, so it is computed correctly on create without this line. Removing it has no functional impact. Forward-Port-Of: odoo/odoo#289007 Forward-Port-Of: odoo/odoo#286132