Friday, August 21, 2026
103 changes · master
Resolved issues and error corrections
This fixes a timing issue on mobile where selecting an item in a modal could target the wrong popup and cause a crash. It makes the affected flow more reliable for users and helps keep automated user journey tests stable.
Original PR description
…tour Scope kanban selection triggers to the active modal to avoid a race with Owl's async modal state, and make Many2XAutocomplete's onClose null-safe against a crash the race was masking. runbot-error-id~939488 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#279300
Opening the Time Off Type details from a new leave request no longer saves or submits the request before the user is finished. This prevents accidental confirmations or approvals and also avoids related display errors that could hide newly created leave requests until refresh.
Original PR description
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls…
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls `willOpenRecordInDialog()`, which defaults to `record.save()`. For a new leave request, this triggered `hr.leave.create()`'s validation logic, auto-confirming (or even auto-approving) the request before the user had finished the wizard. This premature save was also the root cause of two related bugs, both fixed as a side effect: closing the Time Type dialog threw `TypeError: Cannot read properties of undefined (reading 'focus')` (the save re-rendered the parent, leaving `Many2One`'s `onClose` pointing at a stale component), and that crash aborted the promise chain before it could reload the calendar, leaving a newly-created leave request missing from view until a manual refresh. Adds a `many2one_no_save` field widget overriding `willOpenRecordInDialog` to skip the save, applied to `work_entry_type_id` on the base `hr_leave_view_form` so all inheriting views are covered. task-6452848 Forward-Port-Of: odoo/odoo#281263
This change restores expected internal metadata for a Point of Sale popup so automated tests no longer fail unnecessarily. It does not change cashier workflows or business functionality, but helps keep the Point of Sale module stable during validation.
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#277790Sale orders now keep combo product totals consistent when switching between tax-exclusive and tax-inclusive views. This prevents inflated order totals and gives sales teams and customers accurate pricing for combo items.
Original PR description
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines…
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines (e.g. 160.00). 4. Switch the document tax mode from "Tax Excl." to "Tax Incl." using the toggle at the top of the Order Lines tab. **Issue:** - After switching to "Tax Incl." mode, the total on the sale order is higher than the previous untaxed amount (e.g. shows 266.00 instead of the 160.00). - The same switch works correctly on regular (non-combo) product lines **Expected behavior:** - the new total should equal the previous untaxed amount. **Why this happens:** - `_onchange_order_line` is triggered on every `order_line` change, including when switching `document_tax_mode` causes `price_subtotal` to update on existing lines. - The unconditional write to `product_uom_qty` and `discount` on all combo item lines was calling '_compute_price_unit` even when neither value had changed. - `_compute_price_unit` then called `_reset_price_unit` under the new `document_tax_mode`, which re-calculated the stored `price_unit` instead of leaving it untouched for `_compute_amount` to reinterpret correctly. **Fix:** - Only sync `product_uom_qty` and `discount` to the combo item lines whose current values actually differ from the parent line. When no value has changed, no write occurs, so `_compute_price_unit` is not called. opw-6427963 Forward-Port-Of: odoo/odoo#280019
This fix restores automatic SInvoice submission for Vietnamese POS orders when the invoice option is selected. Businesses no longer need to manually send these e-invoices after validating a point-of-sale order, reducing missed submissions and extra admin work.
Original PR description
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a…
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a VN company, the e-invoice is NOT automatically submitted to SInvoice. Users must manually trigger the send wizard. ### Steps to reproduce: 1. Install l10n_vn_edi_viettel_pos, activate VN company 2. Make an order from POS and check the invoice box 3. Observe SInvoice subsmission error ### Cause of the issue: - caused by commit https://github.com/odoo/odoo/commit/4f30306ccc9ff82911f90ed8b3714b212e4b77dc, which decoupled invoice PDF generation from POS order validation by setting `generate_pdf=False` in context when `use_download_invoice` is False (default) - `_generate_pos_order_invoice()` to skip `_generate_and_send()`, which skips VN SInvoice submission. ### Fix: Override `_generate_pos_order_invoice()` to force generating PDF when auto-send to SInvoice is enabled, restoring `_generate_and_send()` during order validation opw-6427675 Forward-Port-Of: odoo/odoo#280932
Authorize.net refunds now correctly handle payments originally made by eCheck/ACH, not just credit cards. This prevents refund failures for settled bank-account payments and helps businesses process customer refunds more reliably.
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
The website setup flow now handles missing theme snippet templates more safely, so one unavailable snippet does not break the whole configurator. This improves reliability for website setup and strengthens the related automated checks.
Original PR description
Fix for the runbot nightly error 944444. bug: The website configurator crashed entirely if one theme snippet's template was missing, instead of just skipping that snippet. steps: Only visible while running `test_01_configurator_translation` fix: Catch MissingError, alongside ValueError, when generating and rendering configurator snippet content. task-6325919 Forward-Port-Of: odoo/odoo#278609
This change makes an automated web test more reliable by allowing extra time for an uploaded image to appear. It helps reduce random test failures during high system load, supporting smoother development and release validation without changing end-user behavior.
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
Self-order purchases for event tickets now keep the selected ticket details through checkout and use the configured ticket price when recalculating totals. This prevents prices from unexpectedly changing to the underlying product price on the payment page, keeping customer charges consistent.
Original PR description
In this commit: - Ensure event ticket information is preserved during self-order processing and use the configured ticket price when recomputing order line prices. - This prevents ticket prices from being replaced by the product price after proceeding to payment and keeps the amounts consistent across the payment page. Task:6375899 Forward-Port-Of: odoo/odoo#282530 Forward-Port-Of: odoo/odoo#275645
The live chat statistics cards now use the full available screen width on mobile devices. This removes awkward empty space and gives users a cleaner, more consistent view when managing live chat from a phone.
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
The hidden avatar count badge now expands properly when the number reaches double digits, such as '+10'. This keeps agent or user counts readable in Live Chat and other screens using avatar lists.
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
Point of Sale now handles sale orders with existing down payments correctly when another down payment is made. This prevents confusing positive and negative duplicate lines on POS orders, improving order accuracy 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
This fix ensures electronic invoices use the correct tax category when transactions involve a supplier or customer in the EEA, such as Swiss suppliers invoicing German customers. It helps avoid incorrect exemption labels and improves compliance for ZUGFeRD/Factur-X invoice reporting.
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#283027 Forward-Port-Of: odoo/odoo#281245
The point of sale customer display now hides the company logo whenever a background image or QR code is shown. This keeps the screen cleaner and prevents the logo from overlapping more important customer-facing content.
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#281749 Forward-Port-Of: odoo/odoo#281406
The portal now decides whether to show the payment methods card using the same rules as the saved payment methods page. This prevents customers from seeing a card that leads to no available payment methods, or missing access when methods are actually available.
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 Forward-Port-Of: odoo/odoo#283173
Generated ISO 20022 payment files now include the state or province and second street line from partner and employee address records. This helps banks, especially in North America, accept wire transfers when complete beneficiary address details are 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 fix restores several point-of-sale payment flows that stopped responding correctly after an internal payment method change. It prevents pending or waiting payments from getting stuck for Mercado Pago, Cashdro, Cashmatic, Safaricom, and bank QR code payments, improving checkout reliability for stores.
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…
*: 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 Forward-Port-Of: odoo/odoo#278977
The product catalog now handles long unit of measure names more gracefully when adding products to sales orders. This prevents text from being cut off, making product quantities and units easier to read for users working with customized unit names.
Original PR description
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the…
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the catalog. Issue: --- - Long UoM names are not fully visible in the catalog view. Root cause: --- - The outer `<div>` has `d-flex` but lacks `w-100`, causing it to overflow its container. Solution: --- - Added `w-100` to the outer `<div>` to prevent overflow. - Adjusted the quantity selector layout for better visibility. Before: --- <img width="388" height="141" alt="image" src="https://github.com/user-attachments/assets/dafae08a-3c9d-4163-8894-daa2e4d26f62" /> After: --- <img width="382" height="154" alt="image" src="https://github.com/user-attachments/assets/abd6f034-be4b-49bf-be9c-c9779de0f30d" /> Enterprise PR: https://github.com/odoo/enterprise/pull/121139 opw-6253382 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282821 Forward-Port-Of: odoo/odoo#267118
When settling a sales order in Point of Sale, extra product attribute add-ons are now preserved on the resulting POS order line. This prevents missing add-on details and helps keep customer orders accurate at checkout.
Original PR description
Before this commit: --- - When a sale order line contained extra attribute addons, those values were not transferred to the POS order line while settling the sales order. After this commit: --- - Preserved extra attribute addons when creating POS order lines from SO. task-6204583 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282160 Forward-Port-Of: odoo/odoo#276143
Point of Sale sample products now load required product attribute information first, preventing an error when setting up sample data after attributes were changed. This helps businesses create demo shops or registers more reliably without manual troubleshooting.
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 Forward-Port-Of: odoo/odoo#281461
The HTML editor now prevents users from opening the dynamic field selector when no target model has been selected, showing a clear notification instead. It also handles outdated or invalid saved field selections more safely, reducing interruptions and avoiding editor crashes when templates or model choices change.
Original PR description
The dynamic field editor assumes that an `Applies To` model is always selected and that existing dynamic fields are always valid for the current model. As a result, trying to insert or edit a dynamic field without selecting a model raised an error. Editing an existing dynamic field after changing the selected model could also crash the field selector when the stored field path was no longer valid. Show a notification when users try to insert or edit a dynamic field without selecting a model, and handle invalid field paths when initializing the field selector to avoid UI crashes. Task-6365420 Forward-Port-Of: odoo/odoo#278544
Clicking a related field in the HTML editor now inserts its readable name by default instead of its internal ID. This makes generated placeholders more useful for users, while still allowing the ID to be selected when needed.
Original PR description
Before this commit: when clicking a field having sub fields (canFollowRelationFor is true), we just return this field's id, which is not very useful in most cases. After this commit: We created subclass of DynamicPlaceholderPopover, EditorDynamicPlaceholderPopover, which uses EditorModelFieldSelectorPopover. We use the display name of the followable field by default and if the user really want the id, they may choose the id subfield. We also show the followable field's name as the default placeholder instead of "Display name". task-6265223 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Uzbekistan accounting setup now classifies current-year and period profit/loss accounts correctly so they are not counted twice in the balance sheet. This improves the accuracy of the Equity section in local financial reports.
Original PR description
Accounts 8710 (Current Year Profit/Loss) and 9910 (Net Profit for the Period) were equity_unaffected, causing their balances to be picked up both by the retained earnings tag-based formula and by the current-year-earnings domain formula in l10n_uz_reports, double- counting them in the balance sheet's Equity section. This commit changes both accounts' type to Equity and adds the BS Line 0540 tag to 9910 (8710 already carried it), so their balances are captured through the tag alone. see https://github.com/odoo/enterprise/pull/128124 see https://github.com/odoo/upgrade/pull/11048 task-6361059
Fixed a minor display issue where some form view button icons could include an unintended “undefined” styling label in the page markup. This keeps the interface markup cleaner and avoids possible styling confusion without changing user workflows.
Original PR description
The `iconClass` prop of `ViewButton` was declared optional with no default value, so it resolved to `undefined` whenever a button arch had an `icon` but no `icon_class` attribute — which is the case…
The `iconClass` prop of `ViewButton` was declared optional with no default value, so it resolved to `undefined` whenever a button arch had an `icon` but no `icon_class` attribute — which is the case for the large majority of stat buttons. The template concatenates that prop into the icon's class string: `this.icon.class + ... + ' ' + this.props.iconClass` so `undefined` was stringified and rendered literally, producing `class="o_button_icon oi undefined"` on the icon element. Give the prop an empty-string default, consistent with `className` in the same props definition. This also covers the components spreading `viewButtonProps` (MultiRecordViewButton, and the Studio button variants in enterprise). Only form views were affected: list and kanban buttons go through `getButtonInfo` in views/utils.js, which already falls back to `""`. Introduced by: https://github.com/odoo/odoo/commit/c5a40a608280017ae9ea8f9e9e1c59f778d629ae task-6485741 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Repair orders under warranty can now be completed when they include service lines linked to a quotation or invoice. The related sales or invoice line is correctly set to a zero price, preventing errors and ensuring warranty services are not charged.
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-pr
Forward-Port-Of: odoo/odoo#278591This update fixes how simplified Italian electronic invoices are generated, including support for virtual stamp duty and correct use of the simplified format when selected. It also prevents simplified invoices from being used for unsuitable recipients, reducing compliance errors for Italian invoicing.
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#283154 Forward-Port-Of: odoo/odoo#274493
Fixed an incorrect styling reference that made titles appear at the wrong size in the website theme preset preview. This helps users see a more accurate preview when choosing or configuring a website theme.
Original PR description
When the conflict of the forward port [1] was resolved, an error was introduced when the class `fs-4` was replaced by `fs-h4`. This commit fixes the class. [1] https://github.com/odoo/odoo/pull/279324 Forward-Port-Of: odoo/odoo#281995
When users try to archive an accounting journal that still has draft entries, the error message now points them to the correct place where those entries can be found and handled. The journal form button was also renamed so it accurately describes that it opens journal items, reducing confusion and helping users complete the archive process.
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. Forward-Port-Of: odoo/odoo#282956
The attendance kiosk no longer loads a presence status component that is not used in that view. This keeps the kiosk experience leaner and avoids unnecessary background resource loading without changing visible 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#282987 Forward-Port-Of: odoo/odoo#282410
Fixes invoice reports so returned dropshipped products no longer show incorrect lot or serial numbers. This helps customers and staff see accurate product tracking information on invoices and credit-note scenarios.
Original PR description
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print on the invoice
-> The generated PDF displays "lot1 & lot2" instead of "lot1"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 2` since the invoice is on a quantity of 2 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic (as they should be): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80
- for the last one, `is_stock_return = False` while it should not, thus the quantity is 1 instead of 0. Furthermore, it does not pass by this code:
https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/sale_stock/models/account_move.py#L79 which would make the quantity for lot2 equalled to 0 (1-1) The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 1, lot2: 0}`
The report selects both lots since it starts with lot1 (qty of 1): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6236855
Forward-Port-Of: odoo/odoo#271282
Forward-Port-Of: odoo/odoo#270599Kiosk receipts no longer show the table tracker number twice. This keeps customer receipts clearer and avoids confusion for staff and guests using self-ordering.
Original PR description
This removes the duplicate table tracker number on the receipt when ordering on kiosk. There is already a floating_order_name field that shows the table tracker number on the receipt when ordering on kiosk. task-6439063 Forward-Port-Of: odoo/odoo#280309
When users update analytic distributions on multiple journal items and create a new distribution model, the creation dialog now remains open so they can finish and save it. This prevents failed or interrupted bulk updates in accounting workflows.
Original PR description
When mass-editing the Analytic Distribution field on several records at once, and creating a new distribution at once, will close the creation dialog before the user could fill it in. Steps to reproduce: - Enable Analytic Accounting - Open Accounting > Journal Items - Enable the Analytic Distribution column - Select 2 journal items and click on the Analytic Distribution - Click on 'Update', fill a distribution, then click "New Model" - Confirm the multi-edit update Issue: The create Analytic Distribution model dialog closes on its own instead of staying open, so the model can never be saved. Analysis: After https://github.com/odoo/odoo/commit/12a61fa5ab7c56a42020c50c683df8ed52f1fb01, in multi-edit, save() ends reloading the list, unmounting the AnalyticDistribution widget, that closes the model dialog it just opened. opw-6405219 Forward-Port-Of: odoo/odoo#281141
This fixes automated checks so Point of Sale sales are validated correctly whether or not stock features are installed. It helps avoid false test failures and keeps invoicing and delivery behavior verified in the right modules.
Original PR description
`test_settle_order_with_different_uom` asserted that settling a sale order line sold in dozens sets `qty_delivered` to 1.0 on the sale order line. That only holds when `pos_sale_stock` is installed: it is its `_prepare_qty_delivered` override that reports the quantities sold in the PoS as delivered, converted back into the unit of the sale order line. `pos_sale` alone only feeds `qty_invoiced`, and since `point_of_sale` does not depend on `stock`, `sale_stock` is not installed either, so `qty_delivered_method` stays 'manual' and the field remains 0.0. Assert `qty_invoiced` instead, which covers the same unit conversion with the modules `pos_sale` actually depends on, and move the `qty_delivered` check to `pos_sale_stock`, where the delivery is created. It is added as its own test since the tests inherited from `TestPoSSale` are not collected by the `pos_sale_stock` suite. runbot-946054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When shoppers sort product listings after applying filters, those filters now remain in place instead of being cleared. This makes browsing more consistent and helps customers refine products without repeating their selections.
Original PR description
Before this commit, changing the sort order after applying shop filters would clear the active filters because the sort links were not updated with the current query parameters. This commit ensures that the sort controls preserve the active filters when changing the sort order. task-6422290
Mega menu layouts now avoid using heading styles where they do not represent real page structure. This keeps the same visual appearance while improving accessibility and helping search engines better understand website pages.
Original PR description
### Issue: Mega menu templates were using heading tags purely for visual styling. This introduces an incorrect document outline, as these elements do not represent actual content hierarchy. It can negatively impact SEO and accessibility. ### Fix: Avoid using heading tags in mega menu templates for visual styling. Use existing CSS classes to preserve the appearance. task-[6116253](https://www.odoo.com/odoo/project/974/tasks/6116253) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes several issues with light users so their role, account status, and employee confirmation indicators behave correctly. It also prevents light users from requesting app installations and adds a demo light user for easier testing and demonstration.
Original PR description
Following light users merge, a few points need to be fixed or modified: - Fix User status Search method - Unstore user role and add search method. - Fix confirmed icon in employee_user_status widget - Remove Apps icon for light users - Switching to light user role is setting the role to user back immediately. - Add Demo Light User More details in commit messages. Task-6476390
Customers editing their portal address in Morocco now receive a clear error when entering an invalid ICE identifier, instead of the save failing silently and logging a backend validation error. This improves the self-service address update experience and reduces confusion or support requests.
Original PR description
Steps: - Install l10n_ma module. - Go to Address page in portal. - Select Morocco country. - Set any random invalid value for ICE input. Issue: - It wont allow to save address and will not give any error or suggestion instead it raises validation error in logger. Cause: - Since recent [fix](https://github.com/odoo/odoo/pull/271969) invalid additional_identifier raises an error for invalid values and in portal we can't display those error directly. Fix: - Validate `additional_identifier` in validate address values and and mark those identifier as invalid field for invalid values to give proper error message and not raise validation error. Also skip `_validate_identifier` for `no_vat_validation` context in creation since we already validate those identifier values. Forward-Port-Of: odoo/odoo#279308
The link preview popover now makes the magic wand edit control easier to click and gives clearer hover feedback. This improves accessibility and usability for users editing links, including in dark mode.
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#283050 Forward-Port-Of: odoo/odoo#276929
Spreadsheet pivot side panels now reflect changed row, column, or measure order immediately. This prevents a brief display of outdated information, making pivot configuration feel smoother and more reliable for users.
Original PR description
Current behavior before PR: - The runtime definition was rebuilt only after load() resolved. - When the row/column/measure order changed without an RPC reload, the side panel kept reading the stale runtime definition. - This caused the side panel to briefly show the old order before updating to the new one. Desired behavior after PR is merged: - Rebuild the runtime definition synchronously in onDefinitionChange. - The side panel now reflects the new order immediately after coreDefinition is updated. Task: [6427932](https://www.odoo.com/odoo/project/2328/tasks/6427932) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an accounting issue where reposting an opening journal entry after resetting it to draft could duplicate related bank statements, statement lines, and payment moves. This helps keep opening balances accurate and prevents extra cleanup work for finance teams.
Original PR description
When the Opening journal entry is reset to draft and then posted again, it duplicates the statement, statement lines, and payment moves linked to the opening balance. This commit ensure no duplicate is created task-6395990
The online shop now avoids showing an extra blank space when a product has no unit of measure label. This creates a cleaner, more polished product availability display for shoppers while preserving unit labels when they are available.
Original PR description
Remove duplicated space when there is no uom_name. Activate the UOM feature in tests to display the uom_name. Following [PR274085](https://github.com/odoo/odoo/pull/274085) where uom_name became conditional. runbot-241108
The record selector now keeps its dropdown indicator from changing the field width when users hover or focus it. Clicking the indicator also opens suggestions as expected, making report filters feel more reliable and easier to use.
Original PR description
Steps to reproduce: - Install Accounting. - Open Reporting > Balance Sheet. - Open the Comparison filter. - Hover the "Percentage of" record selector. - The dropdown width shifts when the caret appears. - Clicking directly on the caret does not open the suggestions. RecordSelector and MultiRecordSelector only displayed their caret on hover/focus, which causes a small layout shift. The caret also acts as a dead click target instead of opening the autocomplete dropdown. Reserve space for the caret in the input, render it without affecting layout width, and make it ignore pointer events so clicking it behaves like clicking the input. task-[6268556](https://www.odoo.com/odoo/project/967/tasks/6268556) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The call debrief panel no longer shows a confusing red error when call timing details are not yet available during ringing or ongoing calls. It also avoids showing temporary speech-to-text processing files as duplicate playable audio, while still keeping real error feedback for loading problems.
Original PR description
Previously, missing start/end datetimes on the parent record displayed a bright-red error banner: "CallDebrief widget needs start and end datetime from the parent record." Since missing dates are expected during ongoing or ringing calls, this message is confusing and unappealing. The widget now silently skips timing initialization, collapsing cleanly until the call is completed. We preserve the error state logic for other actual database or loading failures so that users still receive proper feedback when those occur. Task-6478747 **Enterprise Sibling https://github.com/odoo/enterprise/pull/128185**
This fixes an inventory issue where reducing a delivery quantity could leave the wrong amount reserved when the order and operation lines used different units of measure. Businesses get more accurate stock reservations and transfer quantities, especially when products are handled in packs, dozens, or individual units.
Original PR description
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move…
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the move quantity from 2 to 1 Dozen The move line ends up with 23 Units instead of 12: the decrease of 1 Dozen is applied as 1 Unit on the line and considered fully processed. The remaining 11 units stay reserved and counted on the transfer. Convert the remaining decrease from the move unit to the line unit when taking it from a line, and the taken quantity back to the move unit when updating the remaining decrease. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278411 Forward-Port-Of: odoo/odoo#276774
This update makes Latin American check management clearer and more reliable by improving labels, list behavior, and the visibility of key check details. It also fixes how the system determines whether a check is still on hand, reducing reporting mistakes and preventing changes that could leave checks recorded in the wrong location.
Original PR description
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to…
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to Customer/Vendor depending on the context. - Display the memo and the initial payment's date on the 3rd party checks views. task-5247520 ### Commit 2: [FIX] l10n_latam_check: base checks location on a real on_hand field **Problem 1: On Hand** Whether a check was still on hand had no field of its own: it was computed based on the current_journal_id of the check, while the "On hand" filter approximated it through the payment methods of the check's current journal. The two could disagree, and neither could be searched or grouped on. Expose it as an on_hand computed field, with a compute_sql counterpart so it stays searchable. A check is On Hand if its last posted operation was registered on a cash journal. **Problem 2: Last operation** The sorting of the operations of a check was mostly relying on the payment_date then the write_date and finally the ID. For payments that are registered on the same day, the computation was often wrong as soon as an older payment was edited afterwards, which sent the check back to the journal it had already left. This commit adds a key to the sorting: we now secondly rely on the Journal Entry ID of the payment, which should always exists for posted payments with a check, and is created at posting of the payments so it somehow acts as timestamp of the posting, it also won't re-order if the payments would be reset to draft and re-posted. Finally, and even with changes above, we decided that resetting or cancelling an operation in the middle of the chain of operations should be prevented. It left the check recorded where it no longer was. Note that it is still possible to reset the whole chain at once, or the last operation(s). task-5247520
This fixes an error that could block French branch companies from activating PDP electronic invoicing when their parent company was also selected. Branches now correctly use the parent company's accounting setup, allowing the activation settings to save successfully.
Original PR description
**Steps to reproduce:** * Create a **French** parent company and a branch. * Activate **Electronic Invoicing (PDP)** for the parent company. * Switch to the branch while keeping both the **parent…
**Steps to reproduce:**
* Create a **French** parent company and a branch.
* Activate **Electronic Invoicing (PDP)** for the parent company.
* Switch to the branch while keeping both the **parent company** and the **branch** selected in the company switcher.
* Go to **Settings → French Localization → Activate Electronic Invoicing**.
* Activate **Electronic Invoicing (PDP)** for the branch.
* Select the **Participate in the pilot phase** checkbox and try to save settings.
**Observed behavior:**
* A traceback occurs with the error: `psycopg2.errors.SyntaxError: syntax error at or near ")"` on `IN ()` in the SQL query inside `_force_update_l10n_fr_f10_moves`.
**Cause:**
* `_force_update_l10n_fr_f10_moves` searches for receivable/payable accounts using `company_ids IN companies.ids`.
* A branch company has no accounts assigned directly to it — accounts belong to the parent company — so the search returns an empty list.
* Passing an empty tuple to `IN %(account_ids)s` generates `IN ()`, which is invalid PostgreSQL syntax.
**Fix:**
* Replace `('company_ids', 'in', companies.ids)` with
`('company_ids', 'parent_of', companies.ids)` in the account search
inside `_force_update_l10n_fr_f10_moves`.
* This ensures that accounts owned by a parent company are correctly
found when the given companies are branches, since branch companies
inherit their parent's chart of accounts.
opw-6394650
Forward-Port-Of: odoo/odoo#282849
Forward-Port-Of: odoo/odoo#277232DIN 5008 business documents now show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user's language settings. Footer company register details are also shown more appropriately, avoiding Germany-specific wording where it does not apply.
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…
The website editor now shows dynamic snippet filter names in the editor user's preferred language instead of the website's default language. This avoids 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#282804 Forward-Port-Of: odoo/odoo#275390
This fix prevents Odoo IoT printer handling from trying to cancel a print job that CUPS has already cancelled. It reduces unnecessary printer errors and avoids follow-up failures when tracking cancelled jobs.
Original PR description
Before this commit, if the status of a CUPS job was checked when that job was already cancelled, we would treat it as a generic error and then try to cancel the job again. This would result in an error from CUPS ('client-error-not-possible'). There would then be a secondary exception caused by trying to remove the job ID from the list a second time in the exception handler.
After this commit, we avoid trying to cancel the job again. We also use a set instead of a list to keep track of the job IDs, which prevents duplicates and allows us to discard IDs without causing an error if they are already removed.
sentry-IOT-1J
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283227This fix ensures Malta tax grid assignments are updated correctly when databases are upgraded. It prevents taxes from keeping outdated reporting grids, helping future journal entries and tax reports use the correct Maltese localization setup.
Original PR description
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids…
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids remain unchanged after the upgrade and do not reflect the modifications introduced in [1]. The tax definitions are loaded from CSV data and don't happen during upgrade or module update it did through try_loading". Since the account tags already exist in upgraded databases, the changes are not applied during module loading and the updated grid assignments are not assigned to taxes. **Fix:** Apply the grid update directly through SQL during the upgrade or module update. The change is limited to tax grid assignments and does not require a full tax reload using ``try_loading`` or ``load_data``. **Before fix:** <img width="1458" height="724" alt="image" src="https://github.com/user-attachments/assets/eaac5e3f-d551-4ec0-b282-bb39a50438f9" /> **After fix:** <img width="1240" height="583" alt="image" src="https://github.com/user-attachments/assets/74409c53-dce0-45b2-a6b5-e60f5c2d826d" /> Note: why this fix is needed because existing upgrade script do update move line grid but still tax have the old grid which is weird and will cause issue when journal entry will create. [1]: https://github.com/odoo/odoo/pull/254894/changes/8921186850e31c53072d49a5dc760192f3edb902 opw-6325845 upg-4391393 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272038
Self-order now more reliably checks that combo items belong to the correct parent combo line. This prevents incorrect combo selections from being accepted, helping orders stay accurate 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#283284 Forward-Port-Of: odoo/odoo#281741
A leftover “Request Appraisals” action that caused an error has been removed. Employees can still request appraisals in bulk using the existing “Launch Campaign” option, avoiding confusion and failed workflows.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#127983 Forward-Port-Of: odoo/enterprise#125630
This fix prevents errors when Odoo displays names for multiple salary attachments at the same time. Payroll users can view salary attachment records more reliably without unexpected crashes.
Original PR description
Currently, an error occurs when the display name is computed for multiple salary attachments. `ValueError: Expected singleton: hr.employee(58, 56)` After [recent commit], when computing the display name, the employee's display name is accessed through multiple attachment records at once. This results in accessing the display name of multiple employees simultaneously, which raises a singleton error. This commit ensures that the employee is accessed from each individual attachment record when computing the display name. [recent commit]: https://github.com/odoo/enterprise/commit/d9648ef695903113d6ed2f40cd4fcfdd68221fa8 [1]- https://github.com/odoo/enterprise/blob/d913de3097d06e723a08d24907024f83769b1fb8/hr_payroll/models/hr_salary_attachment.py#L150-L153 sentry-7665634830 Forward-Port-Of: odoo/enterprise#127765
Fixed an issue where switching the AI agent to a pivot view could cause the view to crash or open without selected measures. The pivot view now waits until it is ready before AI adjustments are applied, preserving default measures when none are requested.
Original PR description
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving…
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving the `APPLY_AI_ADJUST_MODEL` bus event. However, the event could be processed while the pivot model was still executing `_loadData()`. In that case, the following sequence occurred: * `_loadData()` started and awaited. * The controller patch was executed. * The patch called `toggleMeasures()`. * `toggleMeasures()` waited for `_loadData()` to complete. * `_loadData()` finished and updated the metadata with the available measures. * `toggleMeasures()` resumed and wrote back the metadata snapshot it had taken before waiting. Since `toggleMeasures()` operates on a snapshot of the metadata, the measures populated by `_loadData()` were lost when the snapshot replaced the current metadata, leaving the pivot model without its `measures` metadata and causing the view to crash. Prevent this race condition by waiting for the pivot model initialization to complete before applying the AI adjustments. Also preserve the default active measures when the AI agent does not explicitly request any measures instead of clearing them and opening an empty pivot view. task-6384368 Forward-Port-Of: odoo/enterprise#125897
Employees opening a contract offer will now see Yes/No benefit options, such as medical insurance, correctly pre-selected when the benefit is already included. This prevents confusion during offer review and helps ensure the salary package shown matches the actual contract offer.
Original PR description
Issue: When an employee opens the salary configurator for a contract offer, optional benefits configured with Yes/No radio choices (such as Medical Insurance) fail to pre-select 'Yes' even when the benefit is already included in the offer. Steps to Reproduce: 1. Go to Salary Configurator and open a contract offer that has an active benefit 2. Observe that 'Yes' is not selected for the benefit on initial load. Fix: Ensure that when a contract offer includes a benefit, the salary configurator automatically defaults the radio selection to `Yes`. task-6392064 Forward-Port-Of: odoo/enterprise#127544
The India salary simulation now avoids running an unnecessary tax calculation when the popup opens. This prevents newly entered values from being cleared and stops misleading missing-field errors for users testing regular pay structures.
Original PR description
Steps :- - On opening the Simulation when India: Regular pay structure is selected, throws "Missing required fields" when fields are changes on form view. Fix:- - For Indian company, the TDS calculation ran in the background while opening the popup, and it was clearing the values just entered. This calculation isn't needed for a simulation, so it is now skipped. task-6392171 Forward-Port-Of: odoo/enterprise#126483
Goal templates in Appraisals will now be created without automatically assigning an employee. This ensures templates appear correctly in the goal template library and can be reused as intended.
Original PR description
Steps to reproduce: - Go to Appraisals > Configuration > Goals > Library and create a goal template. - Or open an employee goal and click "Save as Template". - The created goal template is not visible in the goal template list view. Reason: An employee was set by default on new goal templates upon creation. Solution: Do not assign a default employee when creating a goal template. Task-6443339 Forward-Port-Of: odoo/enterprise#126816
Sendcloud return labels now avoid printing the customer's house number twice in the origin address. This keeps return shipping labels clearer and reduces confusion for customers and warehouse teams processing returns.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
Approval rules in Studio now handle empty rule conditions consistently, avoiding ambiguity about which records should be affected. This helps ensure approvals apply as intended and reduces the risk of incorrect approval requirements.
Original PR description
Before this commit, there was an ambiguity with the usage of filtered_domain ie ``` self.assertTrue(record.filtered_domain(False)) self.assertFalse(record.filtered_domain(Domain(False))) ``` This is because in that case the API of filtered_domain was not respected After this commit, there is no ambiguity as we cast to a Domain the value we obtain from the rule: - False or None: all records should be impacted by the rule => Domain(True) - otherwise, let the domain do its job opw-6431607 Forward-Port-Of: odoo/enterprise#128160 Forward-Port-Of: odoo/enterprise#127676
Kenyan POS receipts now generate the tax authority QR code whenever the required signature is available, instead of depending on an order status that could prevent the URL from appearing. This helps ensure customers receive receipts with the expected SCU information after validated POS orders.
Original PR description
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the…
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the l10n_ke module in 'production' mode * Make an order in POS and validate it > Observation: The receipt doesn't contain the SCU information and QR Why the fix: ------------ Based on the receipt screenshot shared on the ticket (from Odoo 19.3) we can see that some informations are shown on the ticket. The information shown are the one received from the etims api, it means the call went through and the response was received. As the qrCode URL only needs `l10n_ke_oscu_signature` to be generated, we can assume that if this field is set we can safely generate the URL and generate the QR code. https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/models/pos_order.py#L252-L256 Based on this assumption we can change the condition to return the URL or not based on the presence of `l10n_ke_oscu_signature` instead of the state of the order being `sent`. In 19.0, the receipt is showing no info at all (when 19.3 is showing some info like the signature). This is also happening because the URL was falsy. And when that is the case we do not show any SCU information https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/static/src/overrides/components/order_receipt/order_receipt.xml#L56 opw-6352120 Forward-Port-Of: odoo/enterprise#127045
The vehicle salary tab now shows the Benefit In Kind amount with the correct yearly label instead of a monthly one. The label placement was also adjusted so it appears neatly beside the value, improving clarity without changing any payroll calculations or data.
Original PR description
The Benefit In Kind (BIK) amount on the vehicle model salary tab was labelled "/ month" while the underlying value is yearly, mismatching the other fields (CO2 fee, Cost, Total Cost) correctly suffixed. The unit label div was also missing the o_hr_narrow_field class used everywhere else in the module, so the unit label stretched to the far right of the row instead of sitting next to the value. Purely visual fix, no behavior or data change. task-6428222 Forward-Port-Of: odoo/enterprise#127652
This fixes Belgian payroll sick leave handling so a second long sickness period is split correctly after the first 30 days when it is not marked as a relapse. It helps ensure leave classification and payroll calculations follow the expected rules for independent sickness periods.
Original PR description
Steps to reproduce: - Create a STO for an employee of more than 30 days -> this period is split in 30 days STO and x days SGS. - Within the relapse period, create a second STO of more than 30 days and leave the relapse field empty (which is fine if the second STO is not related to the first sickness) -> the period should be split after the first 30 days just like the first STO, but it remains an STO for the whole duration. task-6296152 Forward-Port-Of: odoo/enterprise#128101
This fixes an internal automated test that could fail when Field Service Planning was checked together with another planning-related module. The change keeps the test focused on the intended screen behavior and helps maintain more reliable release validation without changing user-facing functionality.
Original PR description
On runbot, the `test_onchange_break_time_after_removing_dates` test was failing during the "all" build due to the `planning_slot_check_datetimes_set_or_plannable_slot` SQL constraint introduced by the sale_planning module. The test previously used `odoo.tests.Form` as a context manager, which implicitly triggered a database save and flushed the dateless test shift to PostgreSQL. Can resolved this by instantiating the Form in memory to validate the frontend `@api.depends` logic without triggering the cross-module database constraint. runbot-6463625 Forward-Port-Of: odoo/enterprise#127859
Belgian payroll now values assimilated absence periods using the employee's salary at the time of each absence, rather than applying one later salary to all periods. This ensures departure holiday attestations and December double holiday regularizations are calculated more accurately when salaries change during the year.
Original PR description
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all…
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all assimilated absence periods. **For an employee with:** - 20 days of assimilated absence in February with a salary of 2,000. - A salary increase to 3,000 in June. - Another 20 days of assimilated absence in November. ``` The previous computation was: (40 × 3,000) × (3 / 13 / 5) ``` - where all assimilated absence days were valued using the wage applicable on the last day of the previous year. - Instead, the remuneration should be computed using the wage applicable ``` during each assimilated absence period: ((20 × 2,000) + (20 × 3,000)) × (3 / 13 / 5) ``` - Compute the fictitious remuneration using the contract wage applicable to each payslip period so that each assimilated absence is valued with the correct monthly salary before applying the holiday formula. task-5932817 Forward-Port-Of: odoo/enterprise#122848
The Timesheet Assistant now includes time from very small events by adding it to matching larger events instead of ignoring it. This helps suggested timesheets reflect a more accurate total time for users.
Original PR description
## Previous Behavior Before this PR: When events were to small to suggestion Timesheet Assistant would completely discard these events. This lead to a suggestion haveing a lower total time than it should. ## New Expected Behavior After this PR: When an event is too small to suggest and shares its name and group with one or more larger event, the duration of the smaller event is added to the last event with the same name and groupe. task-[6452987](https://www.odoo.com/odoo/project/4105/tasks/6452987) Forward-Port-Of: odoo/enterprise#127915 Forward-Port-Of: odoo/enterprise#127167
The Timesheet Assistant no longer interrupts ongoing always-active activities, such as meetings, with away-from-keyboard entries. This gives users cleaner suggestions, more accurate away-time durations, and corrected Google Meet descriptions.
Original PR description
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet…
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet description was incorrect. ## Steps to Reproduce: 1. Generate an always-active event (e.g., join a meeting in Google Meet). 2. Generate non-key events (e.g., visit a website without an ActivityWatch rule). 3. Go AFK. 4. Generate a new non-key event. 5. The Timesheet Assistant will show three suggestions in the following order: an always-active suggestion, an AFK suggestion, and another always-active suggestion for the same activity. ## New Expected Behavior After this PR: The Timesheet Assistant now blocks the creation of AFK suggestions when the previous key event is marked as always-active. AFK event durations have been updated to ensure their values are accurate. The Google Meet description has also been corrected. task-[6431526](https://www.odoo.com/odoo/project/4105/tasks/6431526) Forward-Port-Of: odoo/enterprise#127299 Forward-Port-Of: odoo/enterprise#127028
This fix ensures salary package benefit fields can be selected correctly, including country-specific benefit fields that were previously excluded. It also prevents an error when saving public benefit field selections, improving reliability for HR salary configuration.
Original PR description
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The…
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The advantage of the whitelist is that it factored in for the allowed countries, so instead of duplicating this logic to benefit fields and implementing it in every l10n, we can check which module the field comes from.
example:
The field [`company_car_total_depreciated_cost`](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_payroll_fleet/models/hr_version.py#L62) cannot be selected as `res_field_id` when it should be possible as we see in the [data](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_contract_salary/data/hr_contract_salary_benefit_data.xml#L6), it is not whitelisted because we dont want to copy its value from a template.
2- Another fix is the inverse of the public field, there's a traceback because the selection field is always converted to a string and cannot be used to browse as is.
```py
File "/data/build/enterprise/hr_contract_salary/models/hr_contract_salary_benefit.py", line 238, in _inverse_res_field_public
record.res_field_id = self.sudo().env['ir.model.fields'].browse(record.res_field_public)
^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields.py", line 1890, in __set__
write_value = self.convert_to_write(value, records)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_relational.py", line 387, in convert_to_write
return value.id
^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_misc.py", line 115, in __get__
raise ValueError("Expected singleton: %s" % record) from None
ValueError: Expected singleton: ir.model.fields('1', '7', '3', '8', '4')
```
Forward-Port-Of: odoo/enterprise#128275
Forward-Port-Of: odoo/enterprise#127743When Planning billing is enabled with Field Service, the system now automatically selects the expected default project. This prevents setup confusion and helps ensure billable planning work is linked to the right project from the start.
Original PR description
Steps to reproduce: - 1. Create a new database and install Planning and Field Service. 2. Open the Planning settings and enable Billing. Issue: - Billing is enabled but no default project is selected. Cause: - The default of `res.company.planning_project_id` references the module's own `fsm_project` xmlid, but it is evaluated before the module's data files are loaded. The ref resolves to nothing and no value is written. Fix: - Set the project in the post-init hook, once the data files are loaded. task-6460106 Forward-Port-Of: odoo/enterprise#127656
ISO 20022 payment files now include the vendor's state or province and second address line when available. This helps prevent North American bank transfer rejections caused by incomplete beneficiary address details.
Original PR description
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but…
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but _get_PstlAdr() also needs to write them out. 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. Emit CtrySubDvsn when the address has a state, before Ctry as required by the element order of the PostalAddress schema, and append street2 to the street address line. 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 Requires odoo/odoo#282518, which makes _get_all_addr() return the state and street2. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#128021 Forward-Port-Of: odoo/enterprise#127958
Payroll validation now correctly opens any required follow-up screen, such as a wizard for missing employee information, instead of silently doing nothing. This helps payroll users understand and resolve validation blockers immediately.
Original PR description
action_validate() called action_payslip_done() without returning its result. When action_payslip_done() returns a client action (e.g. a wizard to fix missing employee data instead of raising), that action was lost and the Validate button appeared to do nothing, with no error or warning shown. task-6373549 Forward-Port-Of: odoo/enterprise#127668
Swiss payroll now uses the employee’s requested time off dates when calculating absence days for flexible schedules. This prevents a one-day leave from being counted as two days due to timezone conversion, helping keep regular wage and accident salary calculations accurate.
Original PR description
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating…
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating the accident salary. Steps to reproduce: * Install Swiss Payroll. * Configure a monthly employee without a working schedule. * Assign one day of accident time off. * Generate the payslip for that month. Cause: The Swiss wage computation derives absence boundaries from the date portion of the leave's UTC datetimes: https://github.com/odoo/enterprise/blob/16c29e1bab34b5bcb2b001477d928ec5eb294a97/l10n_ch_hr_payroll/models/hr_payslip.py#L313-L330 A fully flexible employee's full day leave starts at local midnight. In timezones ahead of UTC, that start is stored on the previous UTC date, so the inclusive calendar day computation adds an extra day. Solution: We need to use the requested time off dates for both payslip range filtering and absence proration. These fields preserve the calendar days selected by the user independently of timezone conversion, while leaving the UTC datetimes and half-day handling unchanged. opw-6435086 Forward-Port-Of: odoo/enterprise#127849 Forward-Port-Of: odoo/enterprise#127513
The Timesheet Assistant now recognizes time spent in spreadsheets and suggests it as "Working in Spreadsheet" instead of grouping it under Documents. This helps users review and submit timesheets with clearer, more accurate activity suggestions.
Original PR description
## Behavior Before the Commit When a user spent time working in a spreadsheet, the Timesheet Assistant grouped this time under "Working in Documents". This occurred because "Spreadsheet" is a module rather than an application, and the Assistant only creates suggestions for applications. As a result, it attempted to fall back to an application and frequently defaulted to the "Documents" application. ## New Expected Behavior After this Commit: When a user spends time in a spreadsheet, the Timesheet Assistant now generates a "Working in Spreadsheet" suggestion. This is enabled by a dedicated list of non‑application modules that allows specific modules to be recognized even when they are not applications. task-[6438536](https://www.odoo.com/odoo/project/4105/tasks/6438536) Forward-Port-Of: odoo/enterprise#128038 Forward-Port-Of: odoo/enterprise#126390
Database neutralization for TikTok Shop data now keeps each shop record uniquely identifiable while removing real shop references. This prevents cleanup failures when multiple active TikTok shops exist, making test or sanitized database preparation more reliable.
Original PR description
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error:…
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error: ```py duplicate key value violates unique constraint tiktok_shop_unique_active_shop` DETAIL: Key (tiktok_shop_ref)=(1) already exists. ``` Root cause: --- - At [1], we are setting `tiktok_shop_ref = 1` for all `tiktok_shop` records. Because `tiktok_shop` enforces a partial unique constraint on `tiktok_shop_ref` for active shops [2], setting the same reference value `1` on multiple active shops violates this constraint. Solution: --- - Update sql to assign a row-unique string to each shop. This strips the real shop reference while maintaining uniqueness across active shop records so neutralization completes cleanly. [1]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/data/neutralize.sql#L1-L8 [2]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/models/tiktok_shop.py#L136-L139 opw-6451715 --- Forward-Port-Of: odoo/enterprise#127532
This fix prevents errors when sales planning data is grouped by customer in setups where the customer field is not stored directly. Businesses get more reliable planning reports, especially when viewing sales order related planning information without the Field Service configuration that stores this field.
Original PR description
Before this commit, #122034 converted the related non-stored `partner_id` field in `planning.slot` into a compute non-stored field with a search method, the problem is that field was used as groupby inside a read_group which causes a traceback since the field is no longer reachable in SQL. This commit alters the groupby in problematic _read_group methods to use partner_id field when it is stored (when field service is installed) otherwise the groupby should be `sale_order_id.partner_id`. Forward-Port-Of: odoo/enterprise#128540
Indian payroll contract validation now shows the wage period that matches the employee contract instead of always referring to a monthly wage. This reduces confusion when allowance totals exceed the wage for contracts using a different pay schedule.
Original PR description
**Steps to reproduce:** - Create an indian employee. - Put total allowance `(basic salary + HRA + standard ALW + Perf bonus + travel ALW) > wage` - We will get validation error in employee stating that allowance sum can't be greater than wage. **Before:** - We were always showing monthly wage in the validation error, which was confusing to the end user. **After:** - We will use field `version.shedule_pay` to show dynamic validation error message. Task: [6449791](https://www.odoo.com/odoo/project/1251/tasks/6449791) Forward-Port-Of: odoo/enterprise#127477
The product catalog opened from Field Service tasks now gives more space to the unit of measure column. This makes item details easier to read and keeps the Enterprise interface aligned with the related Community update.
Original PR description
Steps to produce: --- - Install `Field service` module. - Create a task and open it. - From the task open the catalog from smart button. Update the Product Catalog UI to match the Community PR changes. community PR: https://github.com/odoo/odoo/pull/267118 opw-6253382 --- Forward-Port-Of: odoo/enterprise#128146 Forward-Port-Of: odoo/enterprise#121139
Fixed an issue where the online cart could crash after a rental product was changed back into a regular sales order by removing its rental period. The cart now only shows rental period details when the order is actually still a rental, improving checkout reliability for affected customers.
Original PR description
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install…
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install `website_sale_renting` with demo. - Open website > shop > add the product named `Projector`. - Click Ecommerce in the menu bar > Orders . - Remove the `Confirmed` filter > Click on the top order (should be containing the projector product.) - Remove the `Rental Period` and go to the cart. Error: ``` QWebError: Error while rendering the template: AttributeError: 'bool' object has no attribute 'time' Template: website_sale.shorter_cart_summary ``` Cause: - When the user removes the rental period (`rental_start_date` and `rental_end_date`), both fields are set to `False`. When the cart is opened again, these values trigger the error in [line]. - Since the rental period has been removed from the order, the order is converted to a regular Sales Order (see [PR] and its [task]). Therefore, the Rental Period should no longer be displayed. Solution: - Use `is_rental_order` to determine whether to render the rental period instead of `has_rentable_lines`, since `has_rentable_lines `only checks whether the product is rentable [1], which is determined by the product's `rental_periodicity` [2]. - `is_rental_order` is a better check here because it indicates whether the rental period is actually defined on the order [3]. [line]: https://github.com/odoo/enterprise/blob/7c80c9ffa9e7812267f2ac285e3a3fc5ca501814/website_sale_renting/views/templates.xml#L207 [task]: https://www.odoo.com/odoo/all-tasks/6003684 [PR]: https://github.com/odoo/enterprise/pull/106381/commits/56ec41d81f7536f047a1586a12ea6f6e8414b844 [1]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L140-L143 [2]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order_line.py#L61-L64 [3]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L135-L138 sentry-7663524549 Forward-Port-Of: odoo/enterprise#128084
The Uzbek balance sheet now includes unclosed profit or loss from the current year in the Equity section. This prevents the report from appearing unbalanced before year-end closing while preserving the official report line numbering.
Original PR description
The Uzbek balance sheet was unbalanced because the current year's unclosed profit/loss was not reflected in the Equity section. This commit restructures '[0540] - Retained Earnings' into an aggregate of three lines: realized retained earnings (existing tag-based formula), current year unallocated earnings, and previous years' unallocated earnings, the latter two computed from income, expense and equity_unaffected accounts, scoped to the current and prior fiscal years respectively. This keeps the balance sheet correct both before and after year-end closing, without changing the report's official line numbering. see https://github.com/odoo/odoo/pull/282779 see https://github.com/odoo/upgrade/pull/11048 task-6361059
A test for tax return navigation was updated to work with the latest page layout. This helps keep automated checks reliable so issues in tax return access are caught before release.
Original PR description
Description of the issue this commit addresses: Commit 18a9f995ec52d655803aa436e6367bd8bbb353be added layout wrappers around return cards. The tour still expected kanban records to be direct children so it could not find the DUMMY_TAX return. --- Desired behavior after this commit is merged: This commit changes the selector so the tour can open the tax return with the new layout. --- runbot-[945519](https://runbot.odoo.com/odoo/error/945519)
Mexican payroll processing now handles companies that do not have a tax ID set without crashing. This keeps payslip checks running reliably and avoids blocking payroll work because of an optional company field.
Original PR description
`res.company.vat` is not required and can be `False`. Guard the `len()` call so `_issue_mx_warnings` doesn't crash on payslips for companies without a VAT set.
```py
File "/home/odoo/src/enterprise/saas-19.3/hr_payroll/models/hr_payslip.py", line 1936, in _compute_issues
issues = generate_issue(slip, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 235, in _issue_mx_warnings
if not slip.company_id.l10n_mx_curp and slip._l10n_mx_is_curp_needed():
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 325, in _l10n_mx_is_curp_needed
or len(self.company_id.vat) == 13
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'bool' has no len()
```
Forward-Port-Of: odoo/enterprise#128216This fix adds a required customer scheme identifier to SEPA direct debit payment files. It helps ensure files are accepted by banks that require this field, such as Nordea in Sweden, reducing payment processing failures.
Original PR description
We are missing a SchmeNm node in the InitgPty node. This is mandatory for Nordea in Sweden at least. Such as: ```xml <SchmeNm> <Cd>CUST</Cd> </SchmeNm> ``` task-6385960 Forward-Port-Of: odoo/enterprise#124693
This fixes an internal automated test for account reports by using the correct mock PDF generation step. It helps keep report validation reliable without requiring the real PDF engine during testing, reducing false failures in the release process.
Original PR description
Description of the issue this commit addresses: Commit d3b4294a56a5ead3f5ea60714eccdba586f72ef0 changed `_run_wkhtmltopdf` into a subprocess wrapper. A later FW, 64f46c270e062df94d4ce37e3065b3e0a0ba68db, did not account for that change and continued mocking the method with PDF bytes. When the wkhtmltopdf path is reached, reading from those bytes crashes. --- Desired behavior after this commit is merged: This commit mocks `_run_pdf_engine_without_processing`, whose contract is to return PDF bytes, so the tour can validate without invoking a real PDF engine. --- runbot-[944189](https://runbot.odoo.com/odoo/error/944189) Forward-Port-Of: odoo/enterprise#126634
A typo was corrected in the tax unit filter within accounting reports. This improves the clarity and professionalism of the reporting interface without changing functionality.
Original PR description
https://github.com/odoo/enterprise/pull/112607/changes/a96b12df4c9de580041d9f9421441de0b7bc7b2e The typo is coming from this commit. Task-no task
Several guided onboarding flows were corrected so automated walkthroughs work reliably in robot mode. This helps keep appointment scheduling, expense scanning, payroll, and subscription setup guidance stable and reduces the risk of broken first-use experiences.
Original PR description
… fix onboarding tours for robot mode Fix the JS tours of appointment_tour, hr_expense_extract_tour, payroll_tours and sale_subscription_tour, uncovered by adding them to web_tour's onboarding tours test (community-side commit): - appointment_tour: clipboard-close dialog, gantt cell/button selectors, missing attendee/name selection, sample-data-mode interactions. - hr_expense_extract_tour: wrong CSS classes, an obsolete manual receipt-selection step, and menu navigation. - sale_subscription_tour: missing product/customer/plan selections, wrong field name, and a dirty-form-on-save race after selecting the recurring plan.
This update fixes several usability issues in the Sign and Documents Sign flows, especially on mobile and small screens. Users can now more reliably upload, select, send, and cancel signing requests without empty menus or misaligned controls getting in the way.
Original PR description
- show the sample document button on mobile - do not open an empty signer list when there is only one signer - hide the settings menu when it is empty - allow a signer to cancel the request while signing - align the signer rows in the send request wizard - select the document instead of opening it when importing from Documents - fix the Upload button on the empty page task-6395329
This change makes Belgian payroll configuration tests use a fixed date so results stay consistent over time. It helps prevent false test failures and supports more reliable payroll maintenance without changing user-facing behavior.
Original PR description
Runbot: 945950
The Philippine payroll module now calculates employer cost using cash earnings, employer contributions, and 13th month pay. This gives businesses a more complete and accurate view of employment costs for payroll accounting and reporting.
Original PR description
Calculate employer cost as the sum of all rules under the Cash Earnings, Employer's Contributions categories and 13th month pay. task-6371975
Employer cost totals on Hong Kong payroll payslips have been corrected so they better reflect the employer-paid amounts used in payroll reporting. This helps businesses review payroll costs more accurately, including special payments, reimbursements, expenses, and non-employee salary handling.
Original PR description
The employer cost shown on payslips was incorrect. Employer cost is now the sum of the Gross-Cash, SLSP, ERMPF, FEE, and COMP categories, reflecting cash wages, severance and long service payments, the employer's own MPF contributions, non-employee fees, and other employer-paid benefits. task-5964455
The timesheet timer now only shows entries linked to the user's active companies. This prevents users from running into access errors when editing timesheets that belong to another company context.
Original PR description
### before: get all timesheets in the timesheet systray, this cause access error when trying to edit a timesheet not inside the active company ### after: only the timesheets linked to active companies should be displayed in the timer --- task-6216931
This fix updates internal test setup for VoIP sales and subscription features so required records are created with the right permissions. It helps keep automated checks reliable after a recent change to test user access, reducing false failures in validation pipelines.
Original PR description
With commit https://github.com/odoo/enterprise/commit/a452ee4de2927327b56ae6922f395482e3dbd50f, now test methods run as a dedicated `_test_user` whose groups are limited to the ones defined by `_test_user_groups`. As a result, tests may lack the required groups when setting up their own data. To solve, we create data with sudo(). failing runbot: runbot-945764 runbot-945763
Fixed an issue in Belgian payroll where dismissing the company car update confirmation could leave the backend unresponsive. Users can now safely cancel the prompt without needing to refresh the page, preventing disruption during payroll and DMFA workflows.
Original PR description
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian…
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian employee - Create a DMFA covering that quarter and mark it as done - Change the company car of that employee and save - Click Discard (or the cross) on the confirmation dialog onWillSaveRecord is called from within Record._save, which itself runs inside the model mutex. Awaiting record.discard() from there queued the discard behind the very save that was waiting for it, so neither promise ever settled. Since the save was dispatched through executeButtonCallback, every button of the view and of the overlay container stayed disabled, and the mutex stayed blocked for the rest of the page life, making any later save or discard hang as well. Fire the discard without awaiting it, the way account's currency form controller already does: the hook returns false, the save releases the mutex, and the queued discard then reverts the record. task-6463069
The Project Gantt view no longer shows misleading progress bars on individual task rows when tasks are grouped by assignee in sparse mode. Instead, task rows show allocated hours, making workload information clearer and avoiding incorrect visual cues.
Original PR description
## Current behavior: In the task gantt view grouped by assignees and displayed in sparse mode, task leaf rows reuse the row progress bar and display a misleading visual indicator on each task. ## Expected behavior: It would make more sense to not display anything for the progress bar of each task, rather display the allocated_hours per task ## Steps to reproduce: 1. Open Project tasks in Gantt view 2. Group by Assignees 3. Enable sparse display so each task appears on its own row 4. Notice that task rows show a progress bar that is not meaningful for the task itself ## Cause of the issue: Each task rows currently hasno meaningful progress-bar semantics, bu they still inherit the generic row progress-bar rendering ## Fix: Override the task gantt renderer to hide progress bars, and only show `allocated_hours` for each task opw-6352260 Forward-Port-Of: odoo/enterprise#124618
A minor issue in the Sign app was fixed to prevent the system from trying to use a missing logging component. This helps avoid unnecessary errors during document signing operations and supports smoother reliability.
Original PR description
See https://github.com/odoo/enterprise/pull/121960 Forward-Port-Of: odoo/enterprise#128748
This update fixes issues in Point of Sale screens caused by a framework upgrade. Users can now type in the ticket search box without their input being reset, and order status changes are handled more reliably.
Original PR description
OWL3's useEffect takes one argument, so the OWL2 deps callback is dropped: typing in the ticket-screen search box was overwritten by the default term. From odoo/enterprise#111749 (pos_urban_piper) and #122791 (pos_enterprise). useOnChange for searchInput, which is user-writable and cannot be derived. pos_enterprise needed no effect: isStageChanging = computed(...) replaces it.
Updating spreadsheet pivots now keeps the details side panel stable instead of briefly showing an invalid model message. This improves the user experience by preventing confusing flickers while pivot data refreshes.
Original PR description
Current behavior before PR: - Updating a pivot caused the side panel to flicker. - The panel briefly showed an 'invalid model' error. - Owl 3 rendered the panel while the pivot data was still reloading, exposing its transient loading state. Desired behavior after PR is merged: - Fetch the model validity and label once in the onWillStart hook. - Updates now render correctly without flickering. Task: [6427932](https://www.odoo.com/odoo/project/2328/tasks/6427932)
This fix corrects how negative manufacturing movements are handled in enterprise reporting. It helps keep manufacturing cost reports accurate when products or costs move out negatively, reducing the risk of misleading financial analysis.
This fixes extra spacing in rental product availability messages when the unit of measure is not shown. The change keeps the online shop display tidy and updates tests to cover the intended unit display behavior.
Original PR description
Remove duplicated space when there is no uom_name. Activate the UOM feature in tests to display the uom_name. Following [PR274085](https://github.com/odoo/odoo/pull/274085) where uom_name became conditional. runbot-241108
This fixes several issues in call debriefing and VoIP transcription, including a crash when requesting a transcription, duplicate audio playback during pending transcription, and failed transcription requests caused by inconsistent audio file formats. Business users should see a smoother, more reliable call review experience with fewer interruptions.
Original PR description
Prior to this commit, clicking the "Request Transcription" button crashed the client because `t-on-click="onClickTranscribe"` was missing the `this.` prefix. This commit adds `this.` to the click handler in the template so that Owl correctly finds and calls the method on the component. task-6478747 **Community Sibling https://github.com/odoo/odoo/pull/282908**
This fixes an error that could occur when simulating Belgian payroll ONSS data after payroll configuration versioning was introduced. The system now uses the current payroll settings version instead of outdated company-level settings, helping payroll workflows continue reliably.
Original PR description
With the launch of payroll config versioning, fields were moved from res.company to its versions, this file was trying to reference a field directly from the company instead of its current settings version Task-6485680
DIN 5008 PDF documents now consistently show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user’s language settings. This prevents invoices, quotations, purchase orders, follow-ups, and field service documents from displaying confusing or non-compliant date formats.
Original PR description
* = din5008_account_followup, din5008_industry_fsm **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document layout to **DIN…
* = din5008_account_followup, din5008_industry_fsm
**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.
**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`).
**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.
opw-6392649
Forward-Port-Of: odoo/enterprise#128453
Forward-Port-Of: odoo/enterprise#126006Fixed an issue where DHL return label creation could fail when a sales order included incoterms. The system now sends the required incoterm code correctly, helping users complete deliveries without errors.
Original PR description
Issue ----- When "return" is enabled, users get a traceback if the SO has incoterms. Steps to reproduce ----- - Set up DHL - enable return labels - Create a SO with incoterms & confirm it - Confirm the delivery > Traceback Cause ----- The request sent for the return label contains the incoterm record instead of its' code like in `dhl_rest_send_shipping` https://github.com/odoo/enterprise/blob/f6c94d4ca3ef4211a5ab00bf0b39f6a7675c8f79/delivery_dhl_rest/models/delivery_dhl.py#L371-L372 Which is not JSON serializable ----- Ticket: opw-6430371 Forward-Port-Of: odoo/enterprise#126459
Payroll payment files for Swiss Revolut accounts now include the beneficiary name where required. This helps avoid payment processing issues and supports smoother salary payments through Swiss payroll workflows.
Original PR description
Forward-Port-Of: odoo/enterprise#126632
Users can now move through return items in the kanban view with the up and down arrow keys without triggering an error. This makes reviewing and selecting returns smoother and prevents an interruption in the accounting workflow.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#128308 Forward-Port-Of: odoo/enterprise#125164
* = 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#283315
Forward-Port-Of: odoo/odoo#279085