Friday, September 11, 2026
34 changes · saas-19.4
Resolved issues and error corrections
Payslips now only include public holidays that belong to the employee's payroll company. This prevents holidays from another selected company or country from appearing in worked day lines, reducing payroll confusion and incorrect calculations.
Original PR description
Issue: - Create a public holiday in France, and generate a payslip in Belgium, with both companies selected. - French public holidays will appear in the belgian worked day lines. Fix: replace `self.env.companies.ids` -which returns all selected companies- in `_get_leave_domain` with `self.company_id.ids` to match the company of the current version in the payslip. task-id: 6425963 Forward-Port-Of: odoo/odoo#287638
The Contracts page under Employee Records no longer shows Kanban as a selectable view because that view is not supported. This avoids user confusion and keeps the available display options aligned with what actually works.
Original PR description
We don't have a Kanban view for contracts, but we still allow users to select that view type. After discussion with the team, we've deemed that view unnecessary. Instead of implementing the Kanban view, we'll just remove that option from the "Employee Records" (Contracts) page. opw-6475797 Forward-Port-Of: odoo/odoo#284829
Odoo now avoids trying to refresh a record after its discussion panel has already been closed during view navigation. This prevents an unnecessary error message when users ask the AI assistant to open another view while a full message composer is still open.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
task: 6365003
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287744
Forward-Port-Of: odoo/odoo#287125The Point of Sale customer list now loads faster when many customers are present. Menu controls for each customer are only prepared when needed, reducing freezes and improving responsiveness on slower devices.
Original PR description
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine`…
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine` instantiates a full `Dropdown` for its "≡" menu. Setting up a `Dropdown` registers about ten lifecycle hooks (`useDropdownNesting`, `useNavigation`, `useDropdownGroup`, `usePopover`, `useEffect`, ...), and each hook registration eagerly allocates two `OwlError` objects to keep a stack trace. Multiplied by hundreds of rows, this dominates the render: ~60% of the click task is spent constructing errors for menus that will never be opened. Render a plain button per row instead and only mount the `Dropdown`, driven by a `useDropdownState`, once that button is clicked. The `Dropdown` opens its popover on mount when its state is already open and is unmounted again when it closes. The placeholder button keeps the classes the `Dropdown` would add to its toggler so the DOM, the styling and the tour selectors (`button.dropdown`) are unchanged. opw-6453848 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#287564 Forward-Port-Of: odoo/odoo#285974
Point of Sale sessions with stock entries now correctly show the Force Close Session wizard when a closing accounting entry is unbalanced. This prevents sessions from appearing closed without the related accounting entry, helping ensure cash differences are reviewed and posted properly.
Original PR description
When the closing journal entry of a session is unbalanced, `_process_session_validation` in point_of_sale rolls back the transaction and returns the "Force Close Session" wizard action, which…
When the closing journal entry of a session is unbalanced, `_process_session_validation` in point_of_sale rolls back the transaction and returns the "Force Close Session" wizard action, which `_validate_session` returns to the user so the difference can be posted on a chosen account. The pos_stock override of `_process_session_validation` calls `super()` without returning its result. The action is dropped, `_validate_session` carries on, and the session is written as `closed` while the rolled-back entry no longer exists: `move_id` is empty, the orders stay in `paid`, `cash_real_transaction` stays at 0 and the cash difference is never posted. The user sees a successful close and nothing in accounting. Steps to reproduce: - Use a stock configuration whose costs yield a rounding difference on the closing entry (e.g. AVCO products with a sale and a return whose unrounded costs round differently when split between the expense and valuation lines). - Close the session from the PoS. - The session is closed, no journal entry exists, and no wizard was shown. Return the result of `super()` so the wizard is shown as in 19.0. opw-6543863 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287618
Switching to another view through Ask AI while a full message composer is open no longer triggers an error. The system now avoids trying to refresh a chatter area that has already been closed, making navigation smoother and preventing disruptive error messages.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
community: https://github.com/odoo/odoo/pull/287125
task: 6365003
Forward-Port-Of: odoo/enterprise#131184
Forward-Port-Of: odoo/enterprise#131112The customer list in Point of Sale now loads faster when many customers are available. Customer balances are calculated once per row and matched using the correct linked company record, reducing delays and avoiding mistakes with similarly named customers.
Original PR description
Opening the customer list with a few hundred partners is slow; part of the time is spent in `getPartnerCredit`. The `PartnerLine` template reads `this.partnerInfos` eight times per row, and each call runs `getPartnerCredit` again. For a contact, that method resolves the partner carrying the due by scanning every loaded partner for one named like `parent_name`, so the cost grows with the square of the number of partners. Cache the getter in a template variable so it is evaluated once per row, and resolve the due partner through the loaded `commercial_partner_id` instead of the name scan. This is also what the server sums the dues by, and it no longer picks a wrong homonym. `refreshTotalDueOfPartner` used the same lookup and now shares it. opw-6453848 Forward-Port-Of: odoo/enterprise#131079 Forward-Port-Of: odoo/enterprise#130015
The Point of Sale product configurator now hides option price badges when a fixed pricelist means those extras will not actually be charged. This prevents customers and staff from seeing misleading add-on prices and keeps displayed pricing aligned with the final order total.
Original PR description
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that…
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that product an attribute with variant creation "Never", with a value carrying an extra price of 1.00 - In the POS, switch to the preset "TAKEOUT" and click the product Issue: The configurator advertises the attribute value with a "+ $ 1.00" badge, but that extra is charged nowhere: the title of the popup and the resulting order line both stay at the 10.00 of the pricelist. Cause: A fixed pricelist rule replaces the whole price of the product, the attribute extra prices included: _compute_price on product.pricelist.item returns fixed_price and never reaches _compute_base_price, the only place where _get_attributes_extra_price is taken into account. getPrice is a faithful port of that and overwrites `basePrice + price_extra` with rule.fixed_price. The configurator, however, rendered its badges out of value.price_extra alone, without ever asking what the pricelist of the order does with it. Fix: Only advertise an extra price when the price of the product actually reflects it, the way website_sale already does with the show_extra_price of _get_additionnal_combination_info. Asking getPrice covers more than a fixed rule: a rule based on another pricelist recurses with no extra either, and a full discount leaves nothing of it. Combo items keep their badges, since computeComboItems adds their extras on top of the combo price, like _get_combo_item_display_price does. opw-6528187 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287740 Forward-Port-Of: odoo/odoo#286475
Point of Sale register closing messages now correctly include cash in/out movements made by managers who do not have accounting access. This prevents false cash differences from appearing after a session is closed, improving trust in cash control reports.
Original PR description
Steps to reproduce: - Give a user PoS Administrator rights and no Accounting rights. - As that user, open a session with cash control, sell something paid in cash and do a Cash Out. - Close the…
Steps to reproduce: - Give a user PoS Administrator rights and no Accounting rights. - As that user, open a session with cash control, sell something paid in cash and do a Cash Out. - Close the register. The closing popup shows the expected cash (opening + cash payments - cash out); enter exactly that amount, the popup shows no difference. - Open the closed session: its chatter says "Closing difference: -X", X being the cash out amount, and "Closing expected" is the amount before the cash out. Issue: The closing control data agrees with the user, but the closing message records a cash difference equal to the cash out. Cause: `_compute_cash_balance` sums `statement_line_ids` with the rights of the current user. Cash moves are `account.bank.statement.line` records, which `_inherits` `account.move`, so the account.move record rules apply to them too. For a PoS user the only such rule is `rule_invoice_pos_user` (`pos_order_ids != False`), and a cash move has no PoS order: unless the user is in `account.group_account_invoice`, their own cash moves are filtered out and `cash_register_balance_end` ignores them, while `get_closing_control_data` sums the lines in sudo. Since da8be203ec32 PoS managers can create cash moves without any accounting group, which made this visible: in 18.0 cash in/out required `account.group_account_invoice`, whose `account_move_see_all` rule makes every move readable. The values stored at closing are right by accident: `_validate_session` reads the lines in sudo just before, and the one2many cache is shared between the sudo and non-sudo environments of the same transaction. The message posted by `update_closing_control_state_session` runs in its own transaction and gets the filtered sum. Fix: Read the cash lines in sudo in `_compute_cash_balance`, as `get_closing_control_data`, `get_cash_in_out_list` and `_validate_session` already do. Users with accounting rights see all lines already, so nothing changes for them. opw-6521591 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287741 Forward-Port-Of: odoo/odoo#286308
This fixes a mismatch between product identifiers sent to Google Analytics 4 and those used in Google Merchant Center. It helps ensure product performance and advertising data line up correctly across Google tools.
Original PR description
Commit d0bf183b053eb0133e6f7e5e04481ca07bff6bb3 fixes a mismatch between GA4 `item_id` and GMC `id` but was missing the fix in `_get_google_analytics_data` method opw-6443326 Forward-Port-Of: odoo/odoo#287745 Forward-Port-Of: odoo/odoo#287590
French PDP Flow 10 responses from the public portal are now processed instead of only being stored. Rejected reports are correctly marked, users can see the rejection details, and corrected reports can be resent.
Original PR description
Flow 10 PPF responses were stored as attachments without being processed. Consequently, rejected reports remained marked as sent, the rejection reason was not shown to users, and corrected reports could not be submitted again. Process the PPF response codes, update the flow state, and log the returned details in the chatter. Keep response attachments separate from the outgoing payload and allow rejected reports to be manually resent with their original moves and a new transmission identifier. no task id Forward-Port-Of: odoo/odoo#287737 Forward-Port-Of: odoo/odoo#287338
This fix prevents users from resetting Saudi e-invoices to draft while they are being submitted to ZATCA in production. It reduces the risk of duplicate submissions and related taxpayer compliance issues, while still allowing test invoices to be reset in sandbox and simulation modes.
Original PR description
Bulk sending is queued: the batch wizard stamps sending_data on the moves and lets the send cron do the work. Before this commit: Reset to Draft stayed available while the moves were being sent, so…
Bulk sending is queued: the batch wizard stamps sending_data on the moves and lets the send cron do the work. Before this commit: Reset to Draft stayed available while the moves were being sent, so the user could reset an invoice mid-submission. The invoice then ended up draft with an accepted submission and could be sent to ZATCA a second time, which ZATCA treats as a taxpayer compliance issue. After this commit: The records are locked on both sides, the way l10n_jo_edi does. Reading the state instead would not help, as a transaction only sees the snapshot taken when it started, in which the move is still posted. 1. When submitting, the moves that cannot be locked are skipped, as another transaction is already working on them. 2. When resetting to draft, the reset is refused if the records cannot be locked, otherwise it applies once the submission it races with committed. Reset to Draft stays available for invoices accepted in Sandbox and Simulation, as deleting or resubmitting test invoices is the point of those modes. Production remains covered by the l10n_sa_edi_is_production check. Steps to reproduce: 1. Install l10n_sa_edi and onboard a sales journal in Sandbox mode. 2. Create and post two invoices. 3. Select them, Action > Send & Print. 4. Select them again, Action > Reset to Draft. task-6267293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284107
This fixes a compatibility issue where some previously exported custom tours could stop Odoo web assets from loading because they contained an extra saved field. Odoo now accepts those existing tours while still checking the important tour steps, helping avoid disruptions for customers using older generated tours.
Original PR description
Tours exported between 37b35f18 and d2ee747d carry a stray `url` key. `validate()` throws on any unknown key at `registry.addValidation()` time, which aborts asset loading for those pre-existing custom tours. Add a `"*"` wildcard to the schema: unknown keys are ignored, `steps` is still validated. 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#287617
The WhatsApp Disconnect button is now only shown to administrators for accounts set up through the onboarding flow. This prevents manually configured accounts from appearing connected while incoming messages have silently stopped, and avoids access errors for regular internal users opening the account form.
Original PR description
`show_disconnect` was true for any account holding a token, so the Disconnect button showed on manually configured accounts as well. Pressing it unsubscribes the webhook on Meta first, then clears the token, and that write is rejected on a manual account since the credentials are required there. Odoo rolls back, Meta does not, so the account keeps looking configured while incoming messages stop. The compute also read `token`, restricted to WhatsApp administrators, while every internal user has read access on `whatsapp.account`, so opening the account form as a regular user raised an AccessError. The button is now shown only for administrators on onboarded accounts, and `button_disconnect` checks write access, since hiding a button does not stop an RPC call and the request to Meta happens before the write that would have been refused. Task-6544628 Forward-Port-Of: odoo/enterprise#130759
Signed quotation documents created through the customer portal are now protected from deletion. This preserves the signed record while quotations are still awaiting payment, reducing the risk of losing important sales documentation.
Original PR description
Issue: A customer who signs a quotation can delete the chatter entry containing the generated signed PDF. For quotations awaiting a wire transfer, this can remove the only retrievable snapshot of the…
Issue: A customer who signs a quotation can delete the chatter entry containing the generated signed PDF. For quotations awaiting a wire transfer, this can remove the only retrievable snapshot of the signed quotation before the order is confirmed. Steps to reproduce: - Create a quotation requiring an online signature and payment. - Sign it from the customer portal and select wire transfer. - Delete the "Order signed by ..." entry from the portal communication history. Cause: The signing endpoint posts the generated PDF as a regular customer authored comment. Portal chatter allows customers to update their own comments, and deleting one clears its attachments, so the signed PDF is physically removed. https://github.com/odoo/odoo/blob/e479111294b11058038defc31505cc81ac1f1821/addons/sale/controllers/portal.py#L348-L358 Solution: Classify the signed document entry as an automated comment. This keeps it visible and attributed to the customer while ensuring that both the portal interface and backend message rules treat its content and attachment as immutable. Regular customer comments keep their existing behavior. opw-6466029 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286578 Forward-Port-Of: odoo/odoo#283595
The HTML editor now correctly reloads the latest saved version when it detects outdated content. This prevents users from being stuck with stale text after overlapping edits, improving confidence that the displayed document matches what is saved on the server.
Original PR description
Before this commit, an editor recovering from a stale document could stop on this error and keep the stale content:
```
Error: Concurency detected while recovering from a stale document. The
last history id of the server is different from the history id received
by the html_field_write event.
at CollaborationOdooPlugin.resetFromServerAndResyncWithPeers
```
This happens because the recovery compares the history id of the record with the one the html_field_write event carried. A write keeps only the last step id in the field, so an event handled after a later write names an id the record no longer holds. As a result, the recovery stops there and the document stays stale.
This commit fixes the issue by taking the history id read from the record as the new server reference, so the editor converges on the document the server holds.
https://runbot.odoo.com/odoo/error/944595
Forward-Port-Of: odoo/odoo#287408German PoS sessions can now close successfully when an order uses an address-type customer contact without its own name. The system uses the displayed customer name as a fallback, preventing blocking errors while keeping required fiscal export data complete.
Original PR description
Steps to reproduce: - German PoS with Fiskaly TSS configured - Set a customer that is an address contact (type invoice/delivery/other) on an order; such a contact has no name of its own, it is…
Steps to reproduce: - German PoS with Fiskaly TSS configured - Set a customer that is an address contact (type invoice/delivery/other) on an order; such a contact has no name of its own, it is displayed with its parent's - Close the session Issue: Closing crashes with "TypeError: 'bool' object is not subscriptable" and the session cannot be closed at all. Cause: _get_dsfinvk_cash_point_closing_data builds the DSFinV-K buyer block from partner.name, which is only guarded by "if partner := o.partner_id". res.partner.name is not required: the res_partner_check_name constraint only enforces it for type='contact', so an address contact stores NULL there and partner.name reads as False, which cannot be sliced. Fix: Fall back on complete_name - what the UI displays for those contacts, "Parent Company, Delivery" - and on a literal when even that is empty, since the buyer name is mandatory in the export. Reading name first leaves the exported value untouched for every partner that has one. opw-6518336 Forward-Port-Of: odoo/enterprise#129709
Kit products now correctly exclude deliveries completed after the selected accrual date when calculating quantities to invoice. This prevents orders from appearing as invoiceable too early, improving revenue cutoff accuracy for delivered-quantity invoicing.
Original PR description
When selling a kit, the qty_delivered_at_date was not ignoring moves that were done after the accrual_entry_date. Steps to reproduce: ------------------- * Create a kit with any component and make it's invoice policy "Delivered quantities" * Create a sale order for this kit and confirm it, change the order date to any date in the past * Validate the picking * Go check the "Invoiced to be issued" * Change the accrual_entry_date to a date before the picking was validated > Observation: The order still appears opw-6290222 Forward-Port-Of: odoo/odoo#285932 Forward-Port-Of: odoo/odoo#274745
Users can now correct descriptions on sale order lines while an order remains open, even after a line has been delivered or invoiced. This removes confusing behavior where editability depended on which columns were visible, while still preventing product changes on processed lines.
Original PR description
Descriptions on order lines become impossible to change after the line is delivered or invoiced, even though the order is still open. Interestingly, hiding the product column makes the description editable again. This shows that editing descriptions is already technically allowed, but currently depends on the column layout, which is confusing for users. Keep descriptions editable until the order is locked or cancelled. This lets users correct text without allowing changes to products on processed lines. Desired behavior after PR is merged: After a sale order is confirmed, users can modify descriptions while the order remains unlocked, regardless of the column layout. Products on processed lines remain protected. @moduon MT-15454 opw-6432243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286621 Forward-Port-Of: odoo/odoo#285946
This fix makes sale order availability forecasts accurate when products are sold or purchased in different units of measure, such as packs versus individual units. It prevents misleading green availability indicators and helps sales teams make more reliable delivery commitments.
Original PR description
Issue: --- The ministock feature is not showing correct forecast on sale order lines due to miscalculation from different uom. Steps: --- 1- Install `Sale` and `Purchase` apps without `stock`. 2-…
Issue: --- The ministock feature is not showing correct forecast on sale order lines due to miscalculation from different uom. Steps: --- 1- Install `Sale` and `Purchase` apps without `stock`. 2- Create a product. Enable the track inventory. 3- Add `Pack of 6` to product's sale packagings. 4- Create a purchase order with 12 units. Confirm and receive. 5- Create a SO. Add a line with quantity = 3 and UOM = `Pack of 6`. As you see the availability icon is green, which is not correct. Also, by setting different uom for the product, the forecast quantities are calculated wrongly. Cause and Fix: --- 1- Inside purchase implementation of `_compute_forecasted_without_stock()` all quantities are converted to `product.uom_id`. However `product_uom_qty` is already in product uom and shouldn't be converted again to product uom. This causes wrong forecast if product has a uom set and purhcase line use different. 2- In `QtyAtDateWidget.initCalcData()` `leftToDeliver` is based on line uom, however, `virtual_available_at_date` is based on product uom itself, causing wrong `forecasted_issue` calculation. 3- Also in the template, the uom name is not fetched correctly, which should be product uom name. opw-6384812
This fix ensures that automatic accounting entries created when changing periods are properly matched and cleared. It prevents leftover non-neutral journal items from cluttering accounting records, helping keep financial data cleaner and more reliable.
Original PR description
The previous code wasn't reconciling the destination and accrual moves, leaving potentially non-neutral journal items and their counterpart polluting the DB. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287524 Forward-Port-Of: odoo/odoo#279766
This fix stops non-product display lines from being selected or copied into manufacturing stock movements. It helps keep manufacturing and inventory records accurate by ensuring only valid sales order lines are linked during production confirmation.
Original PR description
Issue: ====== before this commit, user was able to select a display SOL and at MO confirmation the SOL was copied to the stock move, so we end up with a stock move linked to a display SOL, which is not correct. Solution: ========= - add a domain on the SOL field as first guard layer - add check on the SOL on MO confirmation to prevent copying a display SOL to the stock move opw-6473017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287491 Forward-Port-Of: odoo/odoo#286534
The quotation document form now clearly marks the attachment upload as required before saving. This helps users understand they must select a file first, avoiding confusion when creating quote documents.
Original PR description
When trying to save an empty quotation document from the form view, the save is blocked because the `name` field is required. However, `name` is readonly when no attachment has been selected. As a result, the form doesn't display the required-field decoration on that field, which is confusing. The attachment field should be marked as required in the view instead. This makes it clear that an attachment must be selected first, after which the `name` field becomes available and can be filled in. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287400
When a timesheet date is changed from a linked task, the Timesheet Assistant now updates right away instead of showing the old date until a page refresh. This keeps the assistant in sync and helps users avoid confusion when reviewing or editing timesheet entries.
Original PR description
Steps to Reproduce: - Install timesheet_grid and activate Timesheet Assistant - Open a timesheet and click the task external link - Change the timesheet date from the task form and save Issue: When the timesheet date is changed from the task, the assistant still shows the old date until the page is refreshed Fix: Reload assistant timesheets after the linked task is saved and refresh or clear the selected timesheet based on the new date task-6454988 Forward-Port-Of: odoo/enterprise#130265
The payslip form now keeps wage and worked-days figures contained within their summary cards, even on narrower screens or when amounts are unusually long. This prevents visual overflow and makes payroll information easier to read without changing payroll calculations.
Original PR description
The worked days/wage stat cards on the payslip form used flex-basis-*/bg-100 utility classes but no min-width guard, so the monetary fields (basic_wage, net_wage, sum_worked_days) could overflow past the card's border on narrower screens or with large amounts. Add min-w-0 on the cards so they can shrink within their flex row, and text-break on the big-number fields so long values wrap inside the card instead of spilling out of it. Forward-Port-Of: odoo/enterprise#131031
Scheduled financial reports now use the intended company instead of including all companies by default. This prevents recipients from seeing report figures mixed across multiple companies when automated reports are sent.
Original PR description
This commit https://github.com/odoo/odoo/commit/94ef1127dfa8af17795f39590c8a37edfa117994 changed how with_company() works to ensure it only adds a new company to the allowed companies. This made the reports options include all companies when sent through the cron (since crons have every company enabled by default). This commit fixes this issue by relying on the context key allowed_company_ids instead of with_company(). task-6505248 Forward-Port-Of: odoo/enterprise#129728
This fixes a reconciliation issue where Odoo could create an exchange difference entry even when the selected account did not allow reconciliation. The check now happens in the reconciliation wizard, helping prevent unintended accounting entries and keeping financial records more accurate.
Original PR description
Repro steps: 1) Create two misc entries with different foreign currency amount and different company currency amounts, on an account with "Allow Reconciliation" disabled (one debit, one credit). 2) Go to Journal Items, select both lines and click Reconcile. Issue: An exchange difference entry is generated. Fix: Move the control of the exchange difference moves creation to the account.reconcile.wizard instead of controling it inside action_reconcile of account.move Related PRs: https://github.com/odoo/enterprise/pull/130541 https://github.com/odoo/enterprise/pull/108362 Forward-Port-Of: odoo/enterprise#131145
This fix adjusts Odoo's internal test setup so password checks no longer trigger unnecessary session changes during automated tests. It reduces random test failures and helps keep development and release validation more stable without changing customer-facing behavior.
Original PR description
The test harness patches the CryptContext object to spend less time hashing to decrease total test runtime. Because the hash parameters have changed, every first login (per transaction) per user will result in a hash rotation. The session_id is also rotated when the password hash rotates. When multiple requests are sent to the server while a session rotation is underway, the session datastore holds either a valid, or expired, or logged-out user session. This is a source of indeterminism in tests that can be prevented by always returning None value for replacement hash. REF Runbot; https://runbot.odoo.com/odoo/error/242811 REF Runbot; https://runbot.odoo.com/odoo/error/233722 Forward-Port-Of: odoo/odoo#287350 Forward-Port-Of: odoo/odoo#285710
This change fixes a test setup issue in the Purchase Stock module when running on databases without demo data. It ensures internal reordering rule tests can run reliably in clean environments, reducing false failures for quality checks.
Original PR description
Steps to reproduce ------------------ 1. install purchase_stock in a database without demo data 2. run any test in TestReorderingRule 3. observe the error: can't write on invisible field 'tracking' Note: This fix is only relevant when you run the test on an empty database, the demo data enables the Lots & Serial Numbers. Forward-Port-Of: odoo/odoo#286519
X/Z reports now use a dedicated paid total so category totals match the order lines shown to users, whether prices are tax included or tax excluded. Daily sales reports keep their existing tax-excluded totals, avoiding changes to established reporting behavior.
Original PR description
The per category totals on X/Z reports would use the same total computation that we use for the daily sales report, but the order lines are shown tax included or excluded based on the config for the database. So we could have a category showing a total which is different from the sum of the order lines on that category. This only shows on X/Z reports, but the daily sale report uses the same data, and always displays the tax excluded prices So here I added an extra 'total_paid' field on the report data, which is used on X/Z reports generation, so the category total matches the order lines on X/Z reports, while keeping the original total which is used for daily reports Task-[6538575](https://www.odoo.com/odoo/project/1737/tasks/6538575) Community PR-[#286954](https://github.com/odoo/odoo/pull/286954) Forward-Port-Of: odoo/enterprise#131110
Time off requests now keep the correct duration when an automation rule creates an activity during request creation or editing. This prevents one-day requests from being incorrectly saved as zero days, improving reliability for HR workflows that use automated reminders or follow-ups.
Original PR description
Problem: A time off request is saved with a duration of 0 days instead of 1 day as soon as an automation rule on Time Off has an action that creates an activity. Cause: `_compute_field_value` runs…
Problem: A time off request is saved with a duration of 0 days instead of 1 day as soon as an automation rule on Time Off has an action that creates an activity. Cause: `_compute_field_value` runs the actions while the fields of the computation it wraps are still protected and not written yet. On `hr.leave` the actions run from a computation nested in `_compute_date_from_to`, so `date_from` is empty when the activity notification reads `display_name`, and `_compute_duration` stores 0. Setting `date_from` afterwards does not mark `number_of_days` to compute again since it is protected. Solution: Extract the snapshot `_filter_pre` already does into `_keep_to_compute` and wrap the post filter and the actions with it, so the fields depending on the running computation stay to compute. Same treatment as 488419a5ca49 (odoo/odoo#243611) on the pre filter. Steps to reproduce: - Enable the developer mode. - Go to Settings > Technical > Automation Rules and create a rule on the Time Off model with the trigger On create and edit. - Add an action of type Create Activity, set its Responsible to another user, and save. - Go to Time Off > New, pick an employee and a time off type, and request one working day. - Observe that the request shows a duration of 0 days. Ticket [link](https://www.odoo.com/odoo/project.task/6498783) opw-6498783 Forward-Port-Of: odoo/odoo#287536 Forward-Port-Of: odoo/odoo#286791
This update prevents self-ordering kiosks from showing an unnecessary warning about failing to contact the IoT box on the local network. It helps keep the kiosk checkout experience smoother by avoiding confusing popups in configurations where they should not appear.
Original PR description
This PR fixes the test where iot request triggers a "failed to contact your iot box on local network popup" Forward-Port-Of: odoo/enterprise#129433 Forward-Port-Of: odoo/enterprise#128388
Child contacts linked to Colombian companies are now kept as contacts instead of being treated as separate companies. This restores the expected "Company, Contact" display and lets users find related contacts when searching by the parent company name.
Original PR description
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company…
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company but not its child contacts. Steps to reproduce: - Create a Colombian company with NIT - Add a child contact or address to that company - Filter Contacts by the company name - Observe that the child is displayed separately and is not returned Cause: The Colombian `is_company` computation classifies every partner with a Colombian NIT and qualifying obligations as a company: https://github.com/odoo/enterprise/blob/911686a31d5d3c1539d0dff7d16edf1ce9b101ca/l10n_co_edi/models/res_partner.py#L43-L53 Those fiscal values are commercial fields and are propagated to child contacts. Without checking that the partner is its own commercial entity, children are therefore classified as companies, preventing the standard display name logic from prefixing their parent name. Solution: We need to restrict the Colombian company classification to partners that are their own commercial partner. This preserves the NIT and obligation rules for actual companies while keeping their inherited child records as contacts, restoring both the combined display name and parent name search behavior. opw-6470958 Forward-Port-Of: odoo/enterprise#130373 Forward-Port-Of: odoo/enterprise#128986
Fixed a quotation display issue where enabling the optional Related Intervention column could cause section totals to appear in the wrong place or be cut off. This keeps amounts aligned correctly, making quotations easier to read and reducing confusion for sales and field service users.
Original PR description
Steps to reproduce: --- - Install `industry_fsm_sale` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related Task` column from the column…
Steps to reproduce: --- - Install `industry_fsm_sale` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related Task` column from the column selector. Issue: --- - When the Related Task optional column is enabled, the section line's aggregated Amount value appears in the wrong column or is clipped. Root cause: --- - `getSectionColumns()` computes the section title's colspan as `columns.length - sectionCols.length + 1` [1]. This formula assumes all non-section columns sit in the middle of the list, with the aggregated amount column (`price_subtotal`) anchored at the right end. - The `task_id` [2] field was added via `position="inside"`, which appends it at the end of `<list>` after `price_subtotal` — breaking that assumption by placing a non-section column after the aggregated amount column. - This makes the section title colspan one unit too wide when `task_id` is enabled, shifting the section's aggregated Amount cell past the `price_subtotal` header column. Fix: --- - Changed the xpath to insert `task_id` after the `discount` field, placing it in the middle of the column list where the colspan formula correctly absorbs it into the title span and keeps the amount column aligned. [1]: https://github.com/odoo/odoo/blob/ed22e3c299d6606f8014e2ffdd4a30f5c7be83ec/addons/account/static/src/components/section_and_note_fields_backend/section_and_note_fields_backend.js#L449 [2]https://github.com/odoo/enterprise/blob/2de1512bce6e2bef16ebd45629cbaf0839bebcbf/industry_fsm_sale/views/sale_order_views.xml#L9-L11 Before: <img width="1254" height="262" alt="image" src="https://github.com/user-attachments/assets/7a62c22c-b002-49d9-a75c-f569987f565e" /> After: <img width="1230" height="337" alt="image" src="https://github.com/user-attachments/assets/951f213a-09af-4b07-be30-d69dae2cc51e" /> opw-6472638 --- Forward-Port-Of: odoo/enterprise#130889 Forward-Port-Of: odoo/enterprise#129125