Thursday, September 3, 2026
11 changes · saas-18.3
Resolved issues and error corrections
Event visitors who switch booth categories now see the correct booth options without needing to reload the page. This prevents outdated booth lists from appearing and helps keep exhibitor registration smooth and reliable.
Original PR description
Before this commit, the "Get A Booth" page of an event could keep listing the booths of the category checked on load after the visitor picks another one. Only a page reload brought the right ones…
Before this commit, the "Get A Booth" page of an event could keep listing the booths of the category checked on load after the visitor picks another one. Only a page reload brought the right ones back. The tour webooth_exhibitor_register timed out on that list: FAILED: [5/13] Tour webooth_exhibitor_register -> Step Choose Booth (trigger: .o_wbooth_booths div:contains(OpenWood Demonstrator 2) input:not(:visible)). TIMEOUT step failed to complete within 10000 ms. This happens because the page fetches the booths of the category checked on load, and clicking another category fetches its booths while that first answer is still on its way. The answer coming back last fills the list, and the widget caches it under the category active on arrival, so the booths of the first category land in the cache of the clicked one. This commit fixes the issue by caching an answer under the category it was asked for, and by filling the list only while that category is still the chosen one. https://runbot.odoo.com/odoo/error/110527 https://runbot.odoo.com/odoo/error/161834 Forward-Port-Of: odoo/odoo#286266
Corrects how fixed-rate Cuota taxes are calculated in Mexican payment complements when invoices are partially paid. This helps ensure the electronic payment documents are accepted by Mexican tax authorities and reduces rejected CFDIs for affected customers.
Original PR description
When generating a payment complement, tax base and importe coming from the related invoice are prorated by the percentage actually paid, each rounded independently to the currency precision. The post-fix step that restores the SAT invariant uses a Tasa-only formula (`base = total / (1 + rate)`), so Cuota (fixed amount per unit) taxes keep mismatched values, ending up with `ImporteDR != round(BaseDR * TasaOCuotaDR)`. This leads to CFDIs rejected by the PAC/SAT. Steps to reproduce: - Create a customer invoice with a Cuota IEPS tax (e.g. 26.2569). - Register a partial payment whose amount is not an exact divisor of the invoice total (e.g. one third). - Send the payment CFDI: the resulting Cuota TrasladoDR has an ImporteDR that does not match BaseDR * TasaOCuotaDR, leading to a rejected CFDI. This commit recomputes `importe` from the prorated `base` for Cuota taxes (bypassing the Tasa post-fix) opw-6087564 Forward-Port-Of: odoo/enterprise#113395
Colombian retention certificate reports now calculate the taxable payment base correctly when vendor bills include partial credit notes. This prevents credit notes from being added to the retention base instead of reducing it, improving the accuracy of Fuente, ICA, and IVA reporting.
Original PR description
**STEP TO REPRODUCE** 1. install l10n_co_reports and account_accountant 2. Create a bill, with a line with a retention tax (3.50% RteFte). 3. Create a partial credit note (unit price less than what's on the bill). 4. Goes to the report 'Certificado de Renteciòn en Fuente', and notice the Monto del Pago Sujeto Retenciòn is not correct. **CAUSE** The sql query multiply tax_base_amount by -1 if debit > 0, which means (because we are dealing with vendor bills) the line is from a credit note, but tax_base_amount is already a signed value so credit notes ends up contributing to the tax base amount while they should reduce it. opw-6235830 Forward-Port-Of: odoo/enterprise#129697 Forward-Port-Of: odoo/enterprise#119716
Point of Sale now correctly includes extra variant prices when applying a pricelist that is based on another pricelist. This prevents discounted or chained pricelists from showing prices that are too low, improving pricing accuracy at checkout.
Original PR description
## Steps to reproduce: - Create a product, with never variant, the variant has an extra price of 100 - Make Pricelist 1, just leave it as default - Make Pricelist 2, make it a discount, based on Pricelist 1, for all products - Go to the PoS, click on the created product - Change the pricelist to Pricelist 2 -> the price does not take the extra price into account ## Why the fix: When we have a pricelist based on another pricelist, we recursively calculate the price on the base pricelist. Before this commit, in the recursive call, we gave 0 as the extra price. We now give the extra price in the recursive function call. opw-6500086 Forward-Port-Of: odoo/odoo#285371
The Helpdesk SLA Status Analysis report now measures how long a ticket stayed open from creation until closing, matching the standard Ticket Analysis report. This gives managers accurate SLA reporting instead of showing zero or assignment-time values for tickets assigned immediately.
Original PR description
1. Open Helpdesk > Tickets and create a ticket on the team "Customer Care", assigned to yourself 2. More than an hour later, move it to the "Solved" stage to close it 3. Open Helpdesk > Reporting > Ticket Analysis, switch to the pivot view and pick the "Hours Open" measure -> the ticket holds the hour it stayed open 4. Open Helpdesk > Reporting > SLA Status Analysis and pick the "Hours Open" measure as well -> the ticket holds nothing, as it was assigned as soon as it was created odoo/enterprise#47454 added the "Hours Open" measure of the ticket analysis to the SLA status analysis, but computes it up to the assignment date instead of the closing date. The measure therefore holds the hours until the ticket was assigned, which the report already offers as "Working Hours to Assign". With this commit, both reports count the hours from the creation of the ticket to its closing. Forward-Port-Of: odoo/enterprise#130170
Analytic plan applicability rules now fall back to the default setting on screens that do not provide an accounting-related context, instead of incorrectly applying company-specific invoice rules. This prevents fields such as Work Centers or Employee views from showing analytic distributions as mandatory when they should be unavailable.
Original PR description
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or…
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or Employee views For example, if a plan has: - Default Applicability: Unavailable - A line with Domain: Invoice, Company: My Company, Applicability: Mandatory Opening the analytic distribution on a Work Center shows `Mandatory` instead of the default `Unavailable` ### Cause: In commit https://github.com/odoo/odoo/commit/ffcf2ee1a3185ef73db93bfd95625844506692c5 `_get_score` was updated to return `0.5` when the applicability line's company matches the caller's company, even when no `business_domain` is provided In `_get_applicability`, the loop selects the first rule whose score exceeds the current minimum, which starts at `0`: https://github.com/odoo/odoo/blob/710e056e5171af2ab72d7d7793da3518f12faf5e/addons/analytic/models/analytic_plan.py#L255-L264 A score of `0.5` is enough to win over the default applicability, so a company-only match on a domain-specific rule incorrectly overrides the default when no `business_domain` is passed ### Steps to reproduce: - Install `mrp` and `accountant` with demo data - Enable Analytic Accounting in Settings - Open the Internal analytic plan and edit its applicability line: -- Remove the account prefix -- Default Applicability: Unavailable -- Domain: Invoice, Company: My Company (SF), Applicability: Mandatory - Go to Manufacturing > Configuration > Work Centers - Open any work center and click on Analytic Distribution Before the fix, Internal is shown as Mandatory instead of Unavailable Removing the company from the applicability line confirms the issue opw-6404884 Forward-Port-Of: odoo/odoo#280312
This fix ensures Adyen payment processing reads the correct information from incoming payment messages. It helps avoid payment handling errors caused by using the wrong values from Adyen's response payload.
Original PR description
opw-6512723 Forward-Port-Of: odoo/odoo#284773
This fix ensures gift card refunds in Spanish POS orders are reported with the correct negative sign in TicketBAI XML. This prevents mismatches between product line totals and invoice totals, supporting accurate fiscal reporting.
Original PR description
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and…
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and l10n_es_edi_tbai_pos with demo data - Create a gift card (add a tax to the discount product, any 0%) - start pos, add a product and use the gift card - fulfill the order - go to backend and open that order - In the TicketBAI XML, the values for the giftcard product will be positive, causing an inconsistency between the product line total and the invoice total [1] https://github.com/odoo/odoo/commit/0bbc5ebdcc7e014d87130b2ff9cee98e3aa7479a [2] https://github.com/odoo/odoo/commit/b17c9713e7a3305c240298fa54fcf1bc87a9bb8c FIX - we used to determine `sign` based on each order line's `is_refund` property - this property is quite sensitive as it depends on factors like line's qty, price, is reward or not. - so its better to depend on order's refund property for sign reversal https://github.com/odoo/odoo/blob/4fef2c5b69fac10594fac81b149d542ee4621b13/addons/point_of_sale/models/pos_order.py#L1768 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278042
The Polish bank verification module now avoids processing all existing payment records during installation. This prevents installation failures for companies with large payment histories and makes setup more reliable.
Original PR description
account.payment model computes every record l10n_pl_verification_id at module installation (l10n_pl_bank_verification), causing crash in case of db with a large number of records wrong method name correction: _auto_init instead of init and call super after creating the db column see odoo/odoo#282504 Forward-Port-Of: odoo/odoo#285968
Creating multiple helpdesk teams with website forms no longer adds duplicate Help menus to the website. The website menu is now shared and only removed when no team still uses it, keeping navigation cleaner and avoiding customer-facing confusion.
Original PR description
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3)…
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3) Create 2 helpdesk team with `Website Form` option enable. 4) Navigate to Website. ### **Observed Behavior:** Two Help menus are created. ### **Expected Behavior:** Multiple menus should not be created. ### **Root Cause:** The menu creation logic relies on the following [condition](https://github.com/odoo/enterprise/blob/b66097122ba3a758734ac6fb2b26579c35cb72c2/website_helpdesk/models/helpdesk.py#L111-L112) `team_count_by_website` is built from `_read_group(..., ['website_id'], ...)`, which keys its result by the `website_id` *recordset*, not its id. Looking it up with `team_count_by_website.get(website.id, 0)` therefore always misses and falls back to `0`, so `team_count <= 1` is always `True` regardless of how many teams already exist for that website. The only thing left guarding menu creation is `any(team.website_menu_id for team in teams)`, which only looks at the teams in the current create/write call, not every team on that website. So saving a second team in a separate call always creates another menu. ### Fix: Make the website menu a resource shared by every team with the website form enabled on a given website, instead of "owned" by whichever team created it: - Before creating a new menu, look up other teams (active or archived) that already point to a menu, matched through the `website_menu_id` relation between teams rather than a hardcoded `/helpdesk` URL, so a customized menu URL doesn't cause a duplicate to be created. Reuse that menu when found. - Only delete a menu once no team (active or archived) still references it, checked before removing a team's own reference. **opw-6303846** Forward-Port-Of: odoo/enterprise#121120
UPS deliveries could be rejected when a customer's invoicing address had no name, which can happen by default for existing partners. This fix uses a fallback name so shipments can be confirmed successfully without requiring manual cleanup of those addresses.
Original PR description
Issue ----- By default, invoicing addresses of existing partners are created without a name. This leads to the deliveries being rejected by UPS. Steps to reproduce ----- - Set Up UPS - Create a Customer - Create an invoicing address with no name - Create a SO for the partner & confirm - UPS delivery - Open the picking and confirm it > UPS rejects the shipment /!\ I could not reproduce in testing environment, so this is based off user steps in their production DB. /!\ Cause ----- The partner being used in `_set_invoice` was changed in #119747 but this use case was missed due to the error not occuring in test mode. ----- Ticket: opw-6485164 Forward-Port-Of: odoo/enterprise#128933