Wednesday, September 2, 2026
61 changes · master
Resolved issues and error corrections
This fix prevents time off categories that are not meant to be selectable, such as Attendance, from appearing when users create time off or allocation records. It also avoids confusing balance text being shown for those unavailable categories, helping HR and payroll users choose only valid time off options.
Original PR description
Steps to reproduce: 1. Go to Payroll > Time Off (or Time Off > Management > Allocations). 2. Create a new record or select a cell. 3. Select a time type that has `time_off_selectable` set to False (e.g. Attendance). 4. Observe that the time type is available in selection and appends "(0/0 hours)" to its display name. Cause: - `_compute_display_name` on `hr.work.entry.type` checked `requires_allocation` without verifying if `time_off_selectable` was True. - Selection domains in `hr.leave`, `hr.leave.allocation`, and batch generation wizards did not filter out non-selectable time off types. Solution: - Check `time_off_selectable` alongside `requires_allocation` in `hr.work.entry.type._compute_display_name`. - Enforce `time_off_selectable = True` in selection domains across `hr.leave`, `hr.leave.allocation`, `hr.leave.allocation.generate.multi.wizard`, and `hr.leave.generate.multi.wizard`. Task: 6518178
Polish bank account verification now handles batches where some partners are missing tax or bank details without causing an error. This keeps verification usable for mixed partner lists and avoids interruptions during routine checks.
Original PR description
When we check for multiple partners with some valid and some being incomplete (no vat or no bank account), a traceback is raised This was due to a bracket accessor, changed into a get in this commit. no-task Forward-Port-Of: odoo/odoo#285898 Forward-Port-Of: odoo/odoo#285631
This restores rules that prevent costs for re-invoiced products from being counted twice in project analytics when anglo-saxon accounting is used. It also brings back related test coverage and applies the logic per company, improving accuracy in multi-company workflows.
Original PR description
Restores the sale_project_stock_account module removed by 37b615f14305 ("[REM] sale_, project_stock_account: remove dead code"), which excludes re-invoiced products from the analytic lines generated…
Restores the sale_project_stock_account module removed by 37b615f14305
("[REM] sale_, project_stock_account: remove dead code"), which excludes
re-invoiced products from the analytic lines generated by stock moves
when anglo-saxon accounting is enabled, together with the test covering
it and the project_stock_account filter it extends.
That removal was justified by _account_analytic_entry_move() no longer
existing, concluding that analytic lines are not created from stock
moves anymore. That was true at the time: 08b62a4bbcc6 had dropped the
method along with the override of project_stock_account that filtered
the moves, and skipped the test guarding it in the same commit, so
removing the module turned nothing red. 1d510f2c2e05 then reintroduced
the analytic lines under _create_analytic_move, which is called whenever
moves are done, leaving the module wrongly missing.
_get_valid_moves_domain is restored on the new method, and with it the
exclusion of the re-invoiced products, whose cost is already carried by
the customer invoice under anglo-saxon accounting. 9a614c91ad7d has
since given project_stock_account a _create_analytic_move override that
skips the moves whose operation type has analytic costs disabled; the
restored filter is merged into that override instead of being added
beside it, and _get_valid_moves_domain keeps only the project condition,
the analytic-costs one now being applied to every move.
The exclusion is now decided per move, on the company of the move
itself: the removed code read the flag on the company of the user
processing the delivery, which ignores the company the delivery belongs
to. As the domain is evaluated for each move, the condition moves into
it instead of gating its construction.
TestAnalytics is un-skipped, as TestAnalyticsReinvoice extends it and
would otherwise inherit its skip. The other tests skipped to fast merge
the valuation refactoring are re-enabled separately.
The restored files predate 8a5b99545dfa, which renamed the product field
expense_policy to reinvoice_policy, so the domain and the test use the
new name.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278698
Forward-Port-Of: odoo/odoo#275246This fix keeps a temporary accounting setting from being reused longer than intended during invoice and payment processing. It mainly improves reliability in automated tests and complex transaction flows, with little expected day-to-day impact for users.
Original PR description
This commits stop this context key to be leaked beyond necessary. In practice it's rarely an issue because the browser will do separate rpc calls with a clean context each time. It is particularily a problem while running some tests where everything happens in the transaction. task-none
This fix prevents a rare crash when Intrastat reporting logic is run in company access situations outside the standard user interface. It helps keep Danish, Lithuanian, and Swedish Intrastat processes stable for future customizations or edge-case setups.
Original PR description
Due to some trouble with tests, we found that in some cases, this function is called on the root company, and if the user does not have the access rights to read data from the company (users with system rights have them by default), it will cause a crash. This situation is not possible with the standard UI, but we fix it in case it becomes possible in a future version or customization. Forward-Port-Of: odoo/enterprise#129083 Forward-Port-Of: odoo/enterprise#128217
Opening the Sales Commissions report could fail because one percentage field was still available in the pivot report even though it could not be totaled. The field has been removed from the pivot measures so business users can load and analyze commission reports normally again.
Original PR description
Issue: `achieved_rate` lost its aggregator (set to aggregator=None) in 69e3827df02 so it wouldn't be summed/averaged in the list view, but it was still declared as a measure in the pivot view. Pivot always needs an aggregate function for its measures, so PivotModel's _getMeasureSpecs threw No aggregate function has been provided for the measure 'achieved_rate', crashing Sales > Reporting > Commissions on load. Solution: Remove achieved_rate as a pivot measure, consistent with it already being excluded from list-view totals. opw-6523870
Frontdesk kiosk check-ins no longer trigger an error when a visitor selects a host and the station has no email template configured. The fix ensures email notifications are only required or sent when the necessary template settings are available, keeping visitor registration smooth.
Original PR description
Currently, an error occurs when a visitor record is created through the kiosk in Frontdesk. **Steps to Reproduce;** - Install the `frontdesk` module. - Go to `Employees` and create a new employee or…
Currently, an error occurs when a visitor record is created through the kiosk in Frontdesk.
**Steps to Reproduce;**
- Install the `frontdesk` module.
- Go to `Employees` and create a new employee or open an existing one.
Set the employee's `email` and `work phone`.
- Go to `Frontdes` > `Stations` and create a station.
- Enable `Host Selection` and select that employee.
- Enable `Notify by email` and remove the `Frontdesk email template`.
- Open the `kiosk URL`, fill in the information, click `Browse All Hosts`,
select that `employee`, and click `Continue`.
- Error is logged in the terminal.
**Another case:**
- Clear the `email template`, disable `Notify by email`, and perform `step 6th`.
- The same error is raised.
`ValueError: Expected singleton: mail.template()`
After [recent commit], when a visitor record is created [1] through the kiosk and the selected
host has a work email while Notify by email is enabled on the station, the system attempts to
notify the host by email [2] . During this process, it renders the email body [3] and subject
using the station's mail template, which raises an error [4] when no mail template is configured.
Similarly, when Notify by email is disabled, if the selected host has no linked user record
but does have a work email, the notification falls back to email [5]. This also raises the same
error when no mail template is configured.
This commit ensure a mail template is required whenever Notify by email is enabled on a station.
For the fallback email notification (when the host has no user account), the system checks that
both a work email and a mail template are available before attempting to send the email,
since email notifications are not mandatory in this case.
[recent commit]: https://github.com/odoo/enterprise/pull/108297/changes
[1]: https://github.com/odoo/enterprise/blob/d025c1a6a87a90bdaead4195e5f996d058294604/frontdesk/controllers/main.py#L151-L162
[2]- https://github.com/odoo/enterprise/blob/d025c1a6a87a90bdaead4195e5f996d058294604/frontdesk/models/frontdesk_visitor.py#L112-L113
[3]- https://github.com/odoo/enterprise/blob/d025c1a6a87a90bdaead4195e5f996d058294604/frontdesk/models/frontdesk_visitor.py#L128-L131
[4]: https://github.com/odoo/odoo/blob/c76a3aedf523da6f751960d2b5dfbc0016416ef1/addons/mail/models/mail_render_mixin.py#L765
[5]- https://github.com/odoo/enterprise/blob/d025c1a6a87a90bdaead4195e5f996d058294604/frontdesk/models/frontdesk_visitor.py#L108-L111
sentry-7624715784
Forward-Port-Of: odoo/enterprise#125178Customers are now stopped from completing checkout when pricing rules unexpectedly make a cart total zero while zero-priced product sales are blocked. Instead of hanging at payment, they are sent back to the cart with a clear warning, reducing failed checkouts and support issues.
Original PR description
When 'Prevent Sale of Zero Priced Product' is enabled and a country-group pricelist prices a product at 0 once the customer's country becomes known during checkout, the cart total becomes 0. The 'free order' branch then validated the order at the payment step, which could hang and time out for a cart that is not actually sellable. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286025 Forward-Port-Of: odoo/odoo#284959
This fixes an issue in the Timesheets grid where clicking a day-based cell could get stuck showing the old value instead of cycling through the expected options. Users can now reliably update grid entries without refreshing or reselecting records, reducing friction during timesheet entry.
Original PR description
1. Open Timesheets > Configuration > Settings and set "Encoding Unit" to "Days", then save 2. Open Timesheets > Timesheets > All Timesheets and switch to the grid view 3. Click an empty cell -> it is selected and keeps displaying 0, and further clicks no longer cycle it through 0, 0.5 and 1 day The grid cell components memoise the value they display with `computed()`, but `GridCell` is a plain class whose `value` is mutated in place when the user edits the grid: reading it registers no dependency, and handing the same cell object back to the `cell` signal does not notify either. The memo is therefore never invalidated, and `FloatToggleGridCell.onChange` picks the next value of the range from that frozen value, so the toggle stops advancing as well. With this PR, the cell value is a signal, so every component deriving from it recomputes when the grid is edited. Task-6527559
This update prevents an internal invoice synchronization setting from remaining active longer than intended. It reduces the risk of incorrect behavior in accounting workflows, especially during automated tests or multi-step processing in the same session.
Original PR description
… of `skip_invoice_sync` This commits stop this context key to be leaked beyond necessary. In practice it's rarely an issue because the browser will do separate rpc calls with a clean context each time. It is particularily a problem while running some tests where everything happens in the transaction. task-none
This fix makes sure recent changes to internal reference records are saved before they are read by a direct database lookup. It prevents Odoo from using outdated configuration values in this specific workflow, improving reliability for module data handling.
Original PR description
Steps to Reproduce: - write on ir.model.data to modify noupdate. - _lookup_xmlids still returns the old noupdate value. Example: In [1]: imd = self.env['ir.model.data'] In [2]: xml_id =…
Steps to Reproduce:
- write on ir.model.data to modify noupdate.
- _lookup_xmlids still returns the old noupdate value.
Example:
In [1]: imd = self.env['ir.model.data']
In [2]: xml_id = self.env['ir.model.data'].search([], limit=1)
In [3]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[3]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, False, 149)]
In [4]: xml_id.write({'noupdate': not xml_id.noupdate})
Out[4]: True
In [5]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[5]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, False, 149)]
In [6]: imd.flush_model()
In [7]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[7]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, True, 149)]
Issue:
- _lookup_xmlids is returning values from ir.model.data executing an SQL query w/o flushing.
Fix:
- Add flushing in _lookup_xmlids.
Forward-Port-Of: odoo/odoo#262791Sales users without accounting permissions can now open invoices that use cash rounding when they are allowed to view the invoice. This prevents an unnecessary access error and keeps the sales invoicing workflow working smoothly.
Original PR description
**Behavior:** When a sales user without accounting access rights tries to view an invoice created from a sale order where a cash rounding is applied, an AccessError is raised. This occurs because…
**Behavior:** When a sales user without accounting access rights tries to view an invoice created from a sale order where a cash rounding is applied, an AccessError is raised. This occurs because loading the invoice view triggers `_compute_tax_totals()`, which then passes the invoice's `invoice_cash_rounding_id` to `_get_tax_totals_summary()`. Which then ends up failing when trying to access fields on the `cash_rounding` record due to missing accounting rights, even though the user is allowed to view the parent invoice. This is fixed by ensuring reading fields on `cash_rounding` during tax total computation bypasses the access check using `sudo()`, as the user already has legitimate access to the invoice itself. **Steps to reproduce:** - As an admin, enable cash rounding then create one. - Create an invoice and set the Cash Rounding Method - In debug mode, go to 'Set Default Values' in the debug dropdown and set Cash Rounding Method = your rounding for all users - Go to users, and ensures that Demo has no accounting rights but has sales user rights - As Demo, create a sale order, confirm it, then create the related invoice. - When trying to acces said invoice, you should get an Access Error opw-6379781 Forward-Port-Of: odoo/odoo#284212 Forward-Port-Of: odoo/odoo#278815
Users can now safely discard changes after reordering very long lists of order lines spread across multiple pages. This prevents an error that could interrupt quotation editing and improves reliability when working with large sales documents.
Original PR description
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to…
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to reorder them - Discard all changes (X shaped button) You will have an evaluation error **Behavior:** When loading a list of records exceeding the limit, only parts of the records are saved in `_cache`. When triggering a reordering of said list, all records need to be loaded including the ones on other pages: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/static_list.js#L1139-L1149 `_getResIdsToLoad()` gets all Ids missing from the cache, these are then passed through `._createRecordDatapoint` and will then be stored in `_cache`. The issue is that the Datapoints are getting created with only `activeFields` as data, which in our case are `id` and `sequence` When discarding the changes `._checkValidity()`is called on each Datapoint: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/record.js#L423-L429 And then `._isInvisible()` is called. This is where the issue happens, since only `sequence` and `id` are stored, when we try evaluate `combo_item_id`, which is the condition to see if sequence is invisible, `combo_item_id` is not found and we get an Evaluation Error. This commit prevents going into `._checkValidity()` by adding `this.isInEdition` to the check leading to it, requiring that the record is in 'edit' mode which is not the case for records created with `_createRecordDatapoint()` opw-6399024 Forward-Port-Of: odoo/odoo#281018
Point of Sale sessions can now close correctly when orders include both a lot-tracked product and a kit containing that product. The fix correctly totals quantities across multiple matching order lines, preventing an error that blocked session closing.
Original PR description
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The…
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The Kit product - A combination of Product A and the Kit product 4. Create three different orders with these combinations. 5. Try to close the PoS session. **Issue :** An error occurs when attempting to close the PoS session. The issue is in the pos_mrp module, specifically in the _get_lot_line_qty method. When accessing the following line: `lines_data[move.bom_line_id.bom_id.product_tmpl_id.product_variant_id.id]['order_lines'].qty` we expect order_lines to contain a single record. However, in this scenario, multiple order lines can be returned for the same product. As a result, accessing .qty directly on order_lines raises a singleton error. **Solution :** With this fix, we first retrieve the quantity from each order line and thensum the quantities together. This ensures that multiple matching order lines are handled correctly and prevents the singleton error when closing the PoS session. opw-6442765 Forward-Port-Of: odoo/odoo#285612 Forward-Port-Of: odoo/odoo#281622
Swiss payroll employee records will no longer log unnecessary history entries when pension mutation records are refreshed. This reduces chatter clutter, especially during frequent automated updates, making important employee history easier to review.
Original PR description
Calling `_create_or_update_snapshot` after writing on an employee recomputes `lpp_mutations`, deleting and recreating the linked records. Because `lpp_mutations` was tracked, every `write` on an employee generated unhelpful chatter entries, cluttering important history. This was especially noisy during frequent writes in hourly crons. Disable field tracking on `lpp_mutations` to improve chatter clarity and overall user experience. opw-6285407 --- Forward-Port-Of: odoo/enterprise#129628 Forward-Port-Of: odoo/enterprise#128033
This fix prevents the Belgian payroll Dimona button or badge from disappearing after employee records are autosaved. It ensures HR teams can reliably access the required Dimona action when managing employee onboarding and payroll compliance.
Original PR description
Steps to reproduce: - Create an employee, fill in name, CP, contract start date, wage. - Leave the form without saving manually (e.g. open another record). - Select the employee again: the Dimona button/badge is gone and stays gone regardless of further edits. l10n_be_needs_dimona_in and l10n_be_dimona_next_action are server-computed but readonly=False let autosave submit a stale value, permanently blocking the recompute. Drop the stray readonly=False on both and add a regression test. Task 6515877 Forward-Port-Of: odoo/enterprise#129731 Forward-Port-Of: odoo/enterprise#129648
This fixes an issue in the French PDP registration process where the system referenced outdated field names. The correction helps prevent registration failures after the related routing fields were renamed.
Original PR description
The fields have been renamed in routing_... --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285619
The Tax Excl./Tax Incl. toggle badge no longer shows an unwanted outline when users hover, click, or focus on it. This keeps sales, purchase, and accounting forms looking consistent and avoids a small visual distraction during order entry.
Original PR description
The "Tax Excl."/"Tax Incl." toggle badge showed an unwanted outline in two cases: - On real keyboard/click focus, Bootstrap draws its default focus ring. - On plain mouse hover, useNavigation adds a "focus" class. Also, sale.order and purchase.order views were never given the `tax_mode_badge` class, so the account.scss fix silently never applied to them at all. Forward-Port-Of: odoo/odoo#283798
Incoming vendor bills processed from email will no longer use the saved original email file as the main invoice attachment. This helps ensure users see the actual invoice document preview instead of a broken or irrelevant email copy when emails include embedded PDFs.
Original PR description
When an incoming mail server has the "Keep Original" option enabled, a copy of every incoming mail is stored as original_email.eml. Because it is not a document of the invoice, the system unattaches…
When an incoming mail server has the "Keep Original" option enabled, a copy of every incoming mail is stored as original_email.eml. Because it is not a document of the invoice, the system unattaches it, however it may still be used as main attachment in case no other PDF or image was attached to the message. Steps to reproduce: - Configure an incoming mail server with "Keep Original" enabled, using an alias pointing to a vendor bill journal. - Send a mail to that alias containing an xml embedding a PDF. - Open that bill Issue: The invoice's main attachment points to the .eml file. This occurs because it is set before the PDF is extracted from the xml. Then, when import extracts the PDF, it is added as attachment on the invoice, but we already have a main attachment that won't be overwritten. However, once a pdf or image is added as attachment, the system will show the (broken) preview. opw-6431726 Forward-Port-Of: odoo/odoo#285409 Forward-Port-Of: odoo/odoo#280318
This fix updates a Belgian payroll attendance test so it remains reliable when demo employee data changes the company's worker count. It helps avoid false payroll test failures while preserving confidence that payslip calculations continue to run correctly.
Original PR description
The FFE employer contribution rate depends on the company's current worker count. Additional demo employees installed on runbot can move the company across the applicable threshold and change the expected payslip amounts. This commit update the test expectations according to the computed worker count. [error-939674](https://runbot.odoo.com/odoo/error/939674) Forward-Port-Of: odoo/enterprise#130025 Forward-Port-Of: odoo/enterprise#126887
Customer-facing invoice pages no longer show the salesperson's city or phone number. This keeps invoice and sales order views consistent while reducing the risk of exposing personal employee information, such as home-office location details.
Original PR description
This change aligns the salesperson's information shown to customers on the invoice view with those shown on the sales order view. Now city and phone number are not shown and both views are consistent. This information can be personal information not supposed to be leaked to customers especially the salesperson's city in case of home office. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285845 Forward-Port-Of: odoo/odoo#278497
Uruguay electronic invoicing now uses the exchange rate saved on the original invoice instead of recalculating it later. This prevents credit notes or related documents from showing mismatched rates when currency rates are updated after an invoice is posted.
Original PR description
18.0 introduced an `invoice_currency_rate` field, storing the currency rate used for each invoice. Currently `_l10n_uy_edi_get_used_rate` uses the `currency.convert()` method using the date and company of the invoice. This is vulnerable to inaccuracy if the currency rates are changed after the invoice posting. For example, if an invoiceis posted and the currency rates are updated, the invoice will use the old rate, while `_l10n_uy_edi_get_used_rate` will return the new one. In the case of the customer in the related ticket, this caused their credit note reference currency rate to mismatch with the one on the invoice. This PR changes the `currency.convert()` call to fetching and inverting the `invoice_currency_rate` field. This ensures the returned value will match the one used for the invoice. opw-6456867 Forward-Port-Of: odoo/enterprise#129620 Forward-Port-Of: odoo/enterprise#128190
Incoming VoIP calls that time out and go to voicemail are now clearly marked as missed. This avoids confusing call messages and keeps call records accurate for users reviewing their communication history.
Original PR description
Steps to reproduce: - Call your softphone with your smartphone. - Let the smartphone ring forever. => At some point, you reach the voicemail and the softphone stops ringing but: - The softphone…
Steps to reproduce: - Call your softphone with your smartphone. - Let the smartphone ring forever. => At some point, you reach the voicemail and the softphone stops ringing but: - The softphone displays a weird message with emojis. - The call record stays "Trying to call" (and might *display* "Ended unexpectedly" in 19.2). This commit fixes those two issues by showing a proper "Call missed" message and switching the call record status to "Missed". This is done in 19.2 and not before... because the behavior before is even more problematic: - 19.1: the softphone keeps ringing and crash if you try to answer, that was mostly fixed thanks to [1] and this commit takes profit of those big ameliorations to fix the issue here. - 19.0: you do not even reach voicemail (it stops without saying anything). This was apparently fixed as a side-effect of [2], which we do not consider worth even partially backporting as not critical. [1]: https://github.com/odoo/enterprise/commit/942f32316ab02d8c739fe7fdd5ec2bdde472a68e [2]: https://github.com/odoo/enterprise/commit/d24d7f3406ca47e7ac529d69957b0ad481d553bf task-6453500 Forward-Port-Of: odoo/enterprise#128731 Forward-Port-Of: odoo/enterprise#127075
This fix ensures alerts in the Point of Sale restaurant appointment flow are dismissed after a table is assigned to a booking. It prevents lingering warning messages that could confuse staff during booking and table management.
Original PR description
Steps to reproduce: ==================== - In `pos_restaurant_appointment`, try to reassign a table to a booking. - An alert is shown. - Assign a table to the booking. Issue: ====== - The alert is not dismissed. Cause: ====== - In `pos_alert_plugin`, `dismiss` is updated instead of `_dismiss`. Fix: ==== - Update `_dismiss` instead of `dismiss`. task-6522926 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures mail records clean up temporary calculated data when a store is closed. It prevents memory from building up during long test runs, improving reliability and avoiding browser-session timeouts.
Original PR description
Before this commit, the mail files of WebSuite.test_unit_desktop take the heap from 82 MB to 1665 MB, read on the [MEMINFO] line each file logs after a forced major GC. Past 2 GB that GC stops…
Before this commit, the mail files of WebSuite.test_unit_desktop take the heap from 82 MB to 1665 MB, read on the [MEMINFO] line each file logs after a forced major GC. Past 2 GB that GC stops returning on runbot and the suite dies on "AssertionError: Script timeout exceeded". This happens because a record holds its computeds in a RecordScope that only the deletion of that record destroys, and a test deletes no record. The test teardown calls _runDisposeFns on the store, which stops what each record registered there and destroys the scope of the store alone, so every computed stays an observer of the signals it read. Message.richBody reads a signal of the module-level emojiLoader, so each message ever rendered keeps its store, its env and its app alive for the whole browser session. This commit registers the destruction of a record scope among the dispose functions of the store, so that the store teardown reaches the computeds of every record, as it already reaches the effect of every compute field. The same run then ends on 127 MB. https://runbot.odoo.com/odoo/error/946840
The salary simulation flow now keeps the employee's job information available when benefits are configured. This prevents an error that previously blocked users from validating a salary simulation from an employee record.
Original PR description
Steps to reproduce: - Go to an employee form. - Click on the salary simulation button. - Click on the configure benefits button. - UserError: "Missing required fields: Employee Job". Reason: `employee_job_id` was missing from the calculator form view XML, causing the field to be empty when validating the simulation. Solution: Add `employee_job_id` as an invisible field in the form view. Task-6497089
The Nilvera PDF button now appears only where relevant for Turkish companies, reducing confusion for other users. Invoicing users without administrator rights can now send, fetch, and download Nilvera e-invoices without access errors, and invoices with unknown status are refreshed immediately when requested.
Original PR description
## Description of the issue/feature this PR addresses: Two related Nilvera e-invoice issues affecting Turkish companies: - The "Fetch Nilvera PDF" button appeared for every company, not just Turkish…
## Description of the issue/feature this PR addresses:
Two related Nilvera e-invoice issues affecting Turkish companies:
- The "Fetch Nilvera PDF" button appeared for every company, not just Turkish ones.
- Sending/fetching e-invoices (or fetching the PDF) as a non-admin Invoicing user raised an
AccessError, because the company's Nilvera API key field is restricted to System/Settings users
and several call sites read it without `.sudo()`.
## Current behavior before PR:
- The PDF-fetch button shows on both the list view and form view of `account.move` regardless of
the company's country.
- An Invoicing-only user (no System/Settings access) gets an AccessError when sending/fetching
e-invoices or fetching the PDF, because `_get_nilvera_client` reads
`company.l10n_tr_nilvera_api_key` without `.sudo()`.
## Desired behavior after PR is merged:
- Both buttons are only visible for Turkish companies (the list-view button has no bound record, so
its gate is driven by a new `l10n_tr` session_info/JS context injection instead of a direct field
reference).
- Invoicing users can send/fetch e-invoices and fetch the PDF without hitting an AccessError.
## Things to add on forward-port
The `.sudo()` fix lives inside `_get_nilvera_client` itself (`l10n_tr_nilvera/lib/nilvera_client.py`),
so every caller that goes through it is already fixed automatically once this diff forward-ports.
Only call sites that read `company.l10n_tr_nilvera_api_key` **directly**, bypassing
`_get_nilvera_client`, still need their own `.sudo()`:
### 19.4
- [ ] Fix e-Dispatch/e-Receipt fetch gate-check access error (direct read of the API-key field,
sudo it the same way as `_l10n_tr_nilvera_company_get_documents` in this PR)
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285360
Forward-Port-Of: odoo/odoo#274312Fixes an accounting issue where cost of goods sold could be overstated after a sale was delivered, returned, credited, and sold again. Credit notes are now included so earlier invoices and refunds properly offset each other, improving inventory cost accuracy.
Original PR description
**Steps to reproduce:** - create a storable product with a positive quantity a cost of 10 and average perpetual category - confirm a SO for 1 quantity, validate delivery - confirm invoice for 1 (COGS…
**Steps to reproduce:** - create a storable product with a positive quantity a cost of 10 and average perpetual category - confirm a SO for 1 quantity, validate delivery - confirm invoice for 1 (COGS should be 10) - return the delivery and validate - create a credit note from the invoice for 1 and confirm (COGS should be 10) - return the return and validate - change the standard price to 100 - create an invoice from the SO for 1 and confirm **Current behavior:** cogs are 190 **Expected behavior:** cogs should be 100 **Cause of the issue:** _get_posted_cogs_value doesn't take into account the credit notes (only the account moves with type 'out_invoice' are taken into account in the sum) https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/sale_stock/models/account_move.py#L185-L186 So in our case the first invoice and the credit note don't cancel out each other. The same goes for _get_cogs_qty (which returns the total cogs past + current), in the past cogs it doesn't take into account the quantities of the credit note. https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/sale_stock/models/account_move.py#L172-L174 So the quantity of the first invoice and the one of the credit note don't cancel out each other. As a result, the return value from _get_cogs_value() for the second invoice is : price unit = 100 returned by _get_cogs_price_unit() https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/account_move_line.py#L68 which returned the standard price because the product has an average cost method https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/stock_move.py#L275-L280 cogs_qty = 2 (instead of 1 if credit was taken into account as -1 in the sum) self._get_posted_cogs_value() = 10 (instead of 0 if credit note cogs were taken into account in the sum as -10) return value = (100 * 2 -10)/1 = 190 https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/account_move_line.py#L75 **fix:** if we take into account the credit note the return value will be : (100 * 1 - 0)/1 = 100 the mechanism of the already posted cogs value is there for cases where we only delivered a part of the quantity and then delivered the rest, but in the case where we delivered and then returned (with credit notes) it shouldn't have an impact. Thus the idea to include the credit note so that it can cancel out the first invoice opw-6426111 Forward-Port-Of: odoo/odoo#284151 Forward-Port-Of: odoo/odoo#282893
Spreadsheet thumbnail previews now load correctly after a change in how file data is returned. This helps users recognize and select the right spreadsheet from the document selector without broken or missing previews.
Original PR description
Binary fields now return a POJO `{filename, content}` rather than a simple string, but the code to display spreadsheet thumbnails wasn't adapted.
Task: [6522764](https://www.odoo.com/web#id=6522764&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form)Belgian payroll now calculates holiday pay regularization from the amounts already recovered during the year and the official attestation cap, instead of recalculating from the employee's current salary. This prevents past leave-related payroll values from changing after a salary update, making year-end adjustments more predictable and accurate.
Original PR description
Previously, holiday pay regularization was calculated using the current payslip's wage, causing past leave values to change whenever the salary was updated. Update `_get_holiday_pay_regularization`…
Previously, holiday pay regularization was calculated using the current payslip's wage, causing past leave values to change whenever the salary was updated.
Update `_get_holiday_pay_regularization` to compute the remaining balance directly from historical 90% recovered amounts (`HolPayRec`) and the attestation cap. This ensures the regularization stays fixed based on the wage at the time leave was taken.
During the year, paid leave days deduct 90% of the wage (HolPayRec). During the annual
regularization, this method calculates the adjustment needed to reach 100% of the wage
equivalent, capped by the total attestation amount (amount_to_recover).
Variables:
- recovered_amount: Total 90% leave deductions (HolPayRec) already applied.
- amount_to_recover: Total holiday pay cap from previous year's attestations.
- total_100_pct_wage: 100% wage equivalent ((recovered_amount / 9.0) * 10.0).
- max_recoverable: Upper limit allowed to recover, min(total_100_pct_wage, amount_to_recover).
- regularization_amount: Difference between max_recoverable and recovered_amount.
Formula:
regularization_amount = min((recovered_amount / 9.0) * 10.0, amount_to_recover) - recovered_amount
Return value = -regularization_amount
Examples:
1. Negative Return Value (Deduction / Further Recovery):
- amount_to_recover = €1,000
- recovered_amount = €450 (90%)
- total_100_pct_wage = (450 / 9) * 10 = €500
- max_recoverable = min(500, 1000) = €500
- regularization_amount = 500 - 450 = €50
- Return: -€50 (Deducts remaining 10% from employee).
2. Positive Return Value (Refund / Over-recovery Correction):
- amount_to_recover = €300 (Low attestation cap)
- recovered_amount = €450 (Already recovered throughout the year)
- total_100_pct_wage = (450 / 9) * 10 = €500
- max_recoverable = min(500, 300) = €300
- regularization_amount = 300 - 450 = -€150
- Return: +€150 (Refunds €150 to employee because recovery exceeded the attestation cap).
Returns:
tuple: (-regularization_amount, explanation_info)
Task : 6453625Belgian payroll now counts the employee's final working day when deciding whether a contract meets the short-term employment threshold. This prevents sick leave from being incorrectly treated as unpaid for employees whose contract spans exactly three months.
Original PR description
Steps: - Create a short term employee, contract spanning exactly 3 months - Create a sick leave for the employee - Sick leave is unpaid Cause: - Currently the threshold for determining short term employees was fixed at 3 months exactly, meaning that excludes the last working day of the employee Solution: - Short term employee threshold is now adjusted to take into consideration the last working day of the employee in its computation. Task: 6515351
This fixes a timing issue where the reply box could stay open because suggestion popups reopened after being dismissed. Users get more reliable keyboard behavior when closing replies or popups in the Mail app, especially under slower server conditions.
Original PR description
Two independent causes made "reply: discard on pressing escape" red, one commit each. "[FIX] mail: wait for the mention suggestions before Escape" is the one that fixes the reported failure, and it holds on every branch: the test presses Escape while the mention fetch is in flight, and the suggestions arriving from the server re-open the list that Escape closed, so the re-opened list takes the second Escape and the reply is never discarded. The test now waits for the fetched suggestions before pressing Escape. "[FIX] mail: keep the suggestion list closed on a re-render" backports "[FIX] mail: keep composer suggestion list closed on unrelated re-render", which entered at 19.0 and never came down. Here NavigableList is re-opened on every patch, so opening the emoji picker after Escape brings the dismissed list back, and it then steals the Escape meant for the picker. https://runbot.odoo.com/odoo/error/946314 Forward-Port-Of: odoo/odoo#286041 Forward-Port-Of: odoo/odoo#284725
Fixed an issue where creating a new group in a grouped list view could cause an error when totals or aggregates were shown. This helps users continue data entry smoothly without interruptions in views such as CRM lists.
Original PR description
Adding a new group on a grouped list view with aggregates gives a traceback. This comes from `getFieldCurrencies` and `computeAggregates` which didn't guard for group with no currency aggregates (like a newly created group). Steps to reproduce: - open a list view (CRM) - group by a m2o (Contact) - click on 'Add a Contact' - press Enter => Traceback Forward-Port-Of: odoo/odoo#285920 Forward-Port-Of: odoo/odoo#285325
Users will no longer see an unnecessary warning notification when a pasted internal link cannot generate a preview, such as when the URL contains a typo. The issue is still recorded in the browser console, reducing distraction while keeping diagnostic information available.
Original PR description
When an internal link preview is missing, a notification is displayed to inform the user that the link is likely wrong. This commit logs this information in the console instead of showing it as a notification. Steps to reproduce: - Go to a To-do note - Create a link - Paste the current URL but introduce a typo in "to-do" => A notification was displayed. task-6317849
The website shop builder now shows a brush icon for the products design button instead of a less clear design services icon. This restores a more familiar visual cue, helping users recognize the design action more easily.
Original PR description
The products design button was previously `fa-paint-brush`. It was replaced by the `design_services` Material Symbols instead of the more similar `brush`. This commit changes it back to a brush. task-6377407
This fixes an issue where manufacturing-related accounting entries could be created in an unpredictable order during subcontracting receipt processing. The change makes results more consistent and helps avoid occasional test or reporting inconsistencies caused by identical dates and document names.
Original PR description
The search order on account move line depends on date, move name and id. This search result order can be non deterministic because, when creating account move line from stock valuation, it depends on…
The search order on account move line depends on date, move name and id. This search result order can be non deterministic because, when creating account move line from stock valuation, it depends on the order from a set, but sets are unordered. **Step to reproduce** Run [test_subcontracting_purchase_bill](https://github.com/odoo/odoo/blob/13b2781978b0edad0df0800404276919b767e32b/addons/mrp_subcontracting_purchase/tests/test_mrp_subcontracting_purchase.py#L268) in: Single app, community, with demo data. **Observation** * The search: When doing the search since we didn't specify any order, the search from account.move.line will ordered by: https://github.com/odoo/odoo/blob/3dd41395e2e4205fa477eb474d4a4dba0a976154/addons/account/models/account_move_line.py#L23 https://github.com/odoo/odoo/blob/3dd41395e2e4205fa477eb474d4a4dba0a976154/addons/account/models/account_move_line.py#L1664 Since, for the components the date and move name are the same it will only depend on the aml ids: * `Account.move.line` creation: When it validate the receipt (`button_validate`) https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp_subcontracting_purchase/tests/test_mrp_subcontracting_purchase.py#L296 It will mark as done the picking (`_action_done`) and the productions (`button_mark_done`) linked to this picking. https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/stock/models/stock_picking.py#L1429 https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp_subcontracting/models/stock_picking.py#L49 Modify the inventory accordingly (`_post_inventory`) https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp/models/mrp_production.py#L2231 while inside of `_post_inventory`, it will process all the production moves, for this it will divided them in set to process them by batch: https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/mrp/models/mrp_production.py#L1904-L1911 From this set, it will create the `account.move.line`: It retrieve the actual stock move with the browse, and call `_action_done`, from where the stock valuation layer will create the `account.move.line`. https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/mrp/models/mrp_production.py#L1913 https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/stock_account/models/stock_move.py#L187 The issue arise because a set read order is non deterministic. runbot-939794 Forward-Port-Of: odoo/odoo#279396
Self-order payment notifications no longer include full order details when sent through live updates. This reduces unnecessary data sharing while keeping order status updates working for customers and staff.
Original PR description
Remove the order data from the websocket notification. Forward-Port-Of: odoo/odoo#285517 Forward-Port-Of: odoo/odoo#284631
Fixed an issue that could prevent users from opening WhatsApp Business account settings after switching Odoo to another language, such as French. The page now relies on a language-independent identifier, so translated labels no longer cause an error.
Original PR description
Currently, an error occurs when a user tries to view the WhatsApp Business account. **Steps to Reproduce:** - Install the `whatsapp_oauth` module. - Go to `Settings` > `Languages` and add `French…
Currently, an error occurs when a user tries to view the WhatsApp Business account. **Steps to Reproduce:** - Install the `whatsapp_oauth` module. - Go to `Settings` > `Languages` and add `French (BE)`, then `switch to it`. - Go to `WhatsApp` > `Configuration` > `WhatsApp Business Accounts (Comptes Whatsapp Business)`. `ValueError: L'élément '<xpath expr="//div[contains(normalize-space(.), 'Receiving Messages')]">' ne peut être localisé dans la vue parente` When the user changes the language, the text in the view is translated [1]. Since the WhatsApp account view tries to locate the div using the plain text Receiving Messages [2]. Since the text has been translated in the parent view, the XPath can no longer locate the element and raise the error. This commit ensures that the XPath uses the name attribute to identify the element, which is language-independent. We cannot use the class attribute because the same class is used by other div elements. [1]- https://github.com/odoo/enterprise/blob/a3db72899cb97612505aebbd5450aeb65205db73/whatsapp/views/whatsapp_account_views.xml#L81-L84 [2]- https://github.com/odoo/enterprise/blob/a3db72899cb97612505aebbd5450aeb65205db73/whatsapp_oauth/views/whatsapp_account_views.xml#L61-L63 sentry-7534862409 Forward-Port-Of: odoo/enterprise#130003
This fix removes Italian eInvoicing fields that were mistakenly shown in the Point of Sale partner form. It keeps the Italian PoS setup aligned with its supported scope, avoiding confusing or unavailable invoicing options for users.
Original PR description
The PoS has a dedicated "simplified" partner form view since 19.2. We had to fix in stable the fields that were missing (typically needed for eInvoicing) in the simplified view by completely overriding the simplified view with the old one. In master, we added the fields back to the simplified view. When doing so, we mistakenly re-added Italian eInvoice fields to the l10n_it_pos module, while this one is not supporting eInvoicing in PoS, only printers, and not even depending on l10n_it_edi that holds the field. This commit removes the extension of the simplified view that was not necessary. Note: added in the same version, no need to handle migration. Related: https://github.com/odoo/enterprise/pull/119316 runbot-946594
Planning shifts will now only show missing-role warnings for human resources, not material resources. This reduces unnecessary alerts when shifts include equipment or other non-human resources that are still valid for the work.
Original PR description
Currently, the warning stating that the resources selected on the shift don't have the required role might be triggered too easily. Human and material resources will likely have different roles due to their different nature. However, a shift can only have a single role, which will usually be the one required for the human resources, while the shift itself may be assigned to a mix of human and material resources. As a result, the warning will often be triggered for material resources even though they are valid for the shift, which could create noise for users. With this PR, the warning is only triggered for human resources Task-6467213
Payroll users can now remove or change payslip period dates without triggering an unexpected error. This keeps payslip creation and editing stable when employee contract dates are present.
Original PR description
Currently, an error occurs when the user removes the payslip period. **Steps to Reproduce:** - Install the `hr_payroll` module. - Go to `Employees` and create an `employee`, or use an existing one. -…
Currently, an error occurs when the user removes the payslip period. **Steps to Reproduce:** - Install the `hr_payroll` module. - Go to `Employees` and create an `employee`, or use an existing one. - Make sure the `employee's version` has a `contract start date`. - Go to `Payroll` > `Payslips` > `Payslips` and create a payslip. - Select that `employee` on the payslip, then remove the `payslip start date`. `TypeError: '<=' not supported between instances of 'datetime.date' and 'bool'` After the [recent commit], which computes the version from the payslip period without allowing it to be overridden, when the user selects an employee whose version has a contract start date, it checks whether the version overlaps with the payslip period [1]. However, since the payslip dates have not yet been set, it raises an error. This commit ensures that the check for the version overlapping with the payslip period is skipped if the payslip does not have both a start and end date. It also makes the method depend on date_to, because if the user changes the payslip end date, it should recheck whether the version overlaps with the payslip period. [recent commit]: https://github.com/odoo/enterprise/commit/569ce2af32477d410b79e98ca72729385042619b [1]- https://github.com/odoo/enterprise/blob/8a66d7beabe6f9b28000ef12725f3a9937d5d1ee/hr_payroll/models/hr_payslip.py#L1716-L1725 sentry-7632216317 Forward-Port-Of: odoo/enterprise#126515
This update registers the Greek e-invoicing module with the translation system. It ensures the module can receive and manage translations properly, improving localization support for Greek users.
Original PR description
Commit https://github.com/odoo/odoo/commit/45bd522dde7a67194e14a40d66944a2e34d1f79d introudced a new module without it's related `weblate.json` entry. This commit fixes this omission. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285570
This fixes a subcontracting receipt issue where partially received items could be incorrectly split into backorders, causing non-subcontracted products to remain fully pending. The added regression coverage helps ensure mixed receipts with subcontracted and regular products are processed consistently.
Original PR description
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units -…
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units - Validate the receipt and create a backorder #### > Only the subcontracted move has been kept on the receipt and a backorder was created for 3 units of P1 and 5 of P2. ### Cause of the issue: Setting the quantity of the subcontracted move will automatically record the quantities on the subcontracted MO: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L83 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L123 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L91 However, the `_update_finished_move` method adds and update the related subcontracted move lines marking them as *picked* to adapt the related reservation: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L118-L164 This is problematic since picking a move line will also pick the move: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/stock/models/stock_move.py#L261-L267 And only picked moves are considered to be processed at picking validation. ### Note: The exact same issue had already been fixed in 17.0: db8b33ebb9fe23507bcba30b12741e4d688ae549 However, the fix had an issue concerning the barcode behavior as it removed the picked computation for subcontracted moves which made hybrid pickings such as the above one (with one subcontracted and one non-subcontracted move) impossible to process in the barcode app. As such, the fix and test where reverted in cf2d18c92bee55ef79db1a338e9baf12f258ee5b The present commit provides an alternative fix of the original issue keeping subcontracted moves unpicked by quantity changes without affecting the picked computation of subcontracted moves (e.g. adding a picked move line on a subcontracted move will still pick that move). Enterprise: https://github.com/odoo/enterprise/pull/123884 opw-6330584 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285614 Forward-Port-Of: odoo/odoo#275304
The Point of Sale flow now hides quotations that have already been settled, so staff cannot accidentally select and settle the same quotation again. This helps avoid duplicate processing and reduces correction work for sales teams.
Original PR description
Once a quotation is settled, opening the quotation list should not allow selecting it again. This commits updates the domain to prevent it. task-6479356 Forward-Port-Of: odoo/odoo#284768
This fix prevents the guided tour feature from crashing when a tour that was previously started is no longer available in the database. Users, including free trial users, should now see the tour handled gracefully instead of encountering an error.
Original PR description
get_tour_json_by_name returned an empty array instead of False when no tour matched. TourService.getTour then skipped its `!tour` guard and crashed reading `tour.steps.length` on that string. Issue spotted on free trials 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#286059
This update makes an internal automated test for the web reference field run consistently, even when there is a small network delay. It helps reduce false failures in Odoo's validation pipeline without changing customer-facing behavior.
Original PR description
The test is non-deterministic and fails with the runbot error:
found 0 elements instead of 1:
0 matching ".ui-autocomplete .ui-menu-item:nth-child(2)"
if there is even a 100ms network delay. clear() dispatches input events, but without flushing the timers, the dropdown state at the time of click(".o_field_reference input") can be out of sync causing no menu items to render and failing the test.
This change makes the sequence deterministic without changing the assertions:
1. runAllTimers() clears the timers and allows the clear of the input to fully go through.
2. click(".o_form_view") unfocus the input so the next click of the input refocuses and triggers the menu opening.
3. checking contains on the dropdown children ensures the menu items can render before click.
runbot error: 940222
Forward-Port-Of: odoo/odoo#286055Fixes an issue where expanding a newly created Calendar event dialog opened a blank form instead of the event just created. This prevents duplicate events from being created for the same time slot and makes quick event creation more reliable.
Original PR description
Problem: In Calendar, dragging a slot opens the quick create dialog. Typing a subject and clicking the expand button in the dialog header creates the event, but the form that opens is empty, and…
Problem: In Calendar, dragging a slot opens the quick create dialog. Typing a subject and clicking the expand button in the dialog header creates the event, but the form that opens is empty, and saving it creates a second event for the same slot. Cause: `FormViewDialog` stores the id of the record it saved in `currentResId`, which `onExpand` passes as `res_id`. `saveRecord` sets it only in the branch that runs when no `onRecordSave` prop is given. `AttendeeCalendarController` passes one since 30478fe855cd (odoo/odoo#239435), so `currentResId` stays false and the action opens a new record. Solution: Set `currentResId` in the shared branch of `saveRecord`. It is private to `FormViewDialog`, so a consumer passing `onRecordSave` cannot set it. Steps to reproduce: - Open Calendar. - Drag a slot in the week view to open the quick create dialog. - Type a meeting subject. - Click the expand button in the dialog header. - Observe that the form opens on a new record while the event is created. Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6476930) opw-6476930 Forward-Port-Of: odoo/odoo#285899
This fixes a dependency issue in the Indian stock localization so related stock and accounting data is available when the app is tested or installed on its own. It helps prevent broken screens in e-waybill stock workflows and improves installation reliability without changing user-facing features.
Original PR description
The view 'l10n_in_ewaybill_stock.view_picking_form_inherit_ewaybill' is broken in single-app tests because it depends on stock.picking:country_code. That field is provided by module 'stock_account' through auto_install relationship. 'stock_account' auto_installs with 'stock' and 'account' installed. This condition exists on stable so it's safe to add this dependency. The dependency is added to l10n_in_stock because it seemed like the logical place where 'account' and 'stock' functionality comes together. [l10n_in_ewaybill_stock] ──[depends]──> [l10n_in_stock] [l10n_in_stock] ──[depends]──> [stock] [l10n_in_stock] ──[depends]──> [l10n_in] ──[depends]──> [account_tax_python] ──[depends]──> [account] REF Runbot: https://runbot.odoo.com/odoo/error/945482 Forward-Port-Of: odoo/odoo#284990
This fixes an issue where applying a color to a selected part of formatted text could color extra nearby text by mistake. Users can now apply text colors more precisely, avoiding unwanted formatting in website or content editing.
Original PR description
Problem: When applying color on a selection that spans across partially selected inline elements (e.g. `<p><b>a[b</b>c]d</p>`), container elements whose contents are not fully selected (such as…
Problem: When applying color on a selection that spans across partially selected inline elements (e.g. `<p><b>a[b</b>c]d</p>`), container elements whose contents are not fully selected (such as `<b>`) were included in `targetedNodes`. This caused improper color formatting/nesting on partially selected elements. Cause: In `ColorPlugin._applyColor()`, `targetedNodes` were filtered by checking `isNodeEditable(node)` and `nodeName !== "T"`, but did not check whether the contents of `node` were fully selected (`areNodeContentsFullySelected(node)`). As a result, partially selected ancestor elements were included in `targetedNodes`. Solution: Filter `targetedNodes` in `_applyColor()` using `this.dependencies.selection.areNodeContentsFullySelected(node)` to ensure only fully selected nodes are targeted when applying colors. Steps to reproduce: 1. Open html_editor. 2. Insert content: `<p><b>ab</b>cd</p>`. 3. Select `b` inside `<b>` and `c` inside `<p>` (`<p><b>a[b</b>c]d</p>`). 4. Apply text color (e.g. red). 5. Observe "ab" and "c" was colored instead of just "b" and "c". task-6456443 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285658 Forward-Port-Of: odoo/odoo#281462
Mexican CFDI invoice XML files now use the customer or user language for unit of measure labels when invoices are sent in bulk. This prevents English labels from appearing unexpectedly in Spanish-language invoices, improving consistency and compliance of generated documents.
Original PR description
### Issue before this commit: When a CFDI invoice was sent through a mass action (Send & Print executed by OdooBot), the unit of measure in the generated CFDI appeared in English instead of the…
### Issue before this commit: When a CFDI invoice was sent through a mass action (Send & Print executed by OdooBot), the unit of measure in the generated CFDI appeared in English instead of the configured language (e.g. Spanish. ### Steps to reproduce the issue: 1.Download Accounting, Contacts and l10n_mx 2. Switch to Spanish (MX) language 3. Set the language of "Inmoviliaria CVA" and "XENON INDUSTRIAL ARTICLES" to Spanish (MX) 4. In contacts select Archived in filters and switch OdooBot language to Spanish (MX) 5. Create and confirm two invoices in the database, one for each customer but don't send these invoices 6. Go to the list view and select these two invoices, and click on "Send and print" and select CFDI 7. Check any of the XML files generated in any of the invoices (in the CFDI tab of the invoice) 8. See that the UoM in the XML file, will be set in english rather than Spanish (MX) ### Cause of the issue: The context under which the batch action runs does not contain the lang key. As a result, translated fields (such as product_uom_id.name) were read in the source language (English) instead of the executing user's language, because nothing in the CFDI generation chain explicitly forced the correct lang into the context. ### Reason to introduce the fix: A CFDI must always report translated fields in the correct language. The fix ensures the invoice is read with the executing user's language when the context doesn't already specify one, so translated fields are consistently correct across both flows. opw-6399860 Forward-Port-Of: odoo/enterprise#129916 Forward-Port-Of: odoo/enterprise#125698
Fixed the Turkish reports journal form so the return from sales account appears in the correct place with the right label. This prevents confusion when users review or configure journal accounts.
Original PR description
The journal form renders `default_account_id` as six standalone labels followed by two `nolabel="1"` fields, one for bank, cash and credit journals and one for sale, purchase and general ones. The xpath matched the first of those two fields, so the return from sales account was inserted between them. Its own label then landed in the middle of the label run, shifting the group grid: both labels rendered side by side with their values underneath, each next to the wrong caption. Anchor on the second field instead, so the new field follows the whole label and field run. Task-6438412 Forward-Port-Of: odoo/enterprise#129532 Forward-Port-Of: odoo/enterprise#128083
Updating suggested products could fail when an unpublished product belonged to an eCommerce category. This fix prevents the error by safely handling cases where no published products are available, allowing staff to update suggestions without interruption.
Original PR description
Currently, an error occurs when the user tries to update suggested products. **Steps to Reproduce:** - Install the `website_sale` module. - Go to `Settings` and enable `Automate suggested products`…
Currently, an error occurs when the user tries to update suggested products.
**Steps to Reproduce:**
- Install the `website_sale` module.
- Go to `Settings` and enable `Automate suggested products` under the `eCommerce` section.
- Go to `Website` > `eCommerce` > `Products` > `Products`.
- Create a `product` and, in the `eCommerce` tab, add a `category`.
- Make sure the `product` is `not published`.
- On the `product`, click the `gear icon` and select `Update suggested products`.
`ValueError: TypeError('unsupported operand types in: product.template() | None') while evaluating 'records.action_update_suggested_products()'`
When the user updates suggested products, the system updates the product's suggested
products - optional, accessory, and alternative products [1]. While updating the alternative
products [2], the system tries to find products based on the categories and attributes shared
with the current product [3]. When retrieving products from the current product's category,
it gets None [4] because the products linked to that category are unpublished and are
therefore excluded by the domain [5]. Later, using this None value raise the error.
This commit ensures that when accessing a missing key in the category dictionary, then it falls
back to an empty product recordset.
[1]: https://github.com/odoo/odoo/blob/21e3310a3eba2ce915b33cf10ee4c14bdda7aad4/addons/website_sale/models/product_template.py#L346
[2]: https://github.com/odoo/odoo/blob/21e3310a3eba2ce915b33cf10ee4c14bdda7aad4/addons/website_sale/models/product_template.py#L384-L386
[3]: https://github.com/odoo/odoo/blob/21e3310a3eba2ce915b33cf10ee4c14bdda7aad4/addons/website_sale/models/product_template.py#L471-L483
[4]- https://github.com/odoo/odoo/blob/21e3310a3eba2ce915b33cf10ee4c14bdda7aad4/addons/website_sale/models/product_template.py#L482
[5]- https://github.com/odoo/odoo/blob/21e3310a3eba2ce915b33cf10ee4c14bdda7aad4/addons/website_sale/models/product_template.py#L445-L456
sentry-7660509183
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281487This fix makes an internal website performance test consistent during parallel test runs. It prevents unrelated demo data from changing the test conditions, helping keep automated validation reliable without affecting normal users.
Original PR description
# Before this commit: The image controller performance test expects the admin partner to be unpublished. In parallel test runs, the website_partner demo data publishes the admin partner, causing the…
# Before this commit:
The image controller performance test expects the admin partner to be
unpublished. In parallel test runs, the website_partner demo data
publishes the admin partner, causing the test to follow a different
code path and fail.
However, during parallel test execution, the website_partner module
installs its demo data, which updates the admin partner:
```
<record id="base.partner_admin" model="res.partner">
<field name="is_published">True</field>
</record>
```
As a result, user_admin.website_published becomes True.
# After this commit:
The test explicitly restores the required precondition by setting the
admin partner's is_published value to False before executing the
performance check.
As a result, the image controller always follows the expected
"unpublished" code path, making the test deterministic regardless of
whether website_partner or any other module with demo data has already
been installed during parallel testing.
Runbot-241102
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278550This fix prevents an error when loading sample work order data after a specific working schedule has been deleted. The system now uses a safe default schedule instead, helping users test or set up Shop Floor without interruption.
Original PR description
Currently, an error occurs when loading the sample data in the Shop Floor. **Steps to Reproduce:** - Install the `mrp_workorder` module. - Go to `Employees` > `Configuration` > `Working Schedules`. -…
Currently, an error occurs when loading the sample data in the Shop Floor. **Steps to Reproduce:** - Install the `mrp_workorder` module. - Go to `Employees` > `Configuration` > `Working Schedules`. - Delete the `Work Center 40 hours/week` record. - Go to `Settings` > `Users & Companies` > `Groups`. - Open the `Manage Work Order Operation` group and add the `Administrator` to the `users` list. - Open the `Shop Floor`. If the `Activate your Work Center` dialog appears, click it and then click `Configure Later`. - Click `Load Samples`. `ValueError: External ID not found in the system: mrp.mrp_workcenter_calendar` After the [recent commit], the sample work center uses the `Work Center 40 hours/week` working schedule instead of `Standard 40 hours/week`. As a result, if the `Work Center 40 hours/week` record is deleted, loading the sample data raises the error [1]. This commit ensures that when the Work Center 40 hours/week calendar is not available, it falls back to `Standard 40 hours/week`, restoring the previous behavior [2]. This fallback is required because `resource_calendar_id` is mandatory from the view perspective, even though it is not required at the model level. If it is left empty, the form displays a missing required field. The `Standard 40 hours/week` calendar is always available because it is linked to the main company [3] and its `resource_calendar_id` field uses `ondelete='restrict'` [4], preventing it from being deleted. [recent commit]: https://github.com/odoo/enterprise/commit/336d721f7b353473fe5e07c29ce14ed77a88fb98 [1]- https://github.com/odoo/enterprise/blob/c0045ec3cf94650d66192a4ca3e0dc3c17daa5bd/mrp_workorder/models/mrp_production.py#L213-L216 [2]- https://github.com/odoo/enterprise/blob/51c1e74e90e510d59aad78820e2c29e821ba2854/mrp_workorder/models/mrp_production.py#L214-L217 [3]: https://github.com/odoo/odoo/blob/4c4219a7d9d51f703b15e83ab755faf1f2c8a71d/addons/resource/data/resource_data.xml#L10-L12 [4]: https://github.com/odoo/odoo/blob/4c4219a7d9d51f703b15e83ab755faf1f2c8a71d/addons/resource/models/res_company.py#L12-L13 sentry-7651161729 Forward-Port-Of: odoo/enterprise#126859
Fixes an error that could block users when creating a second time off accrual allocation with the same plan. This improves reliability for HR teams managing employee leave balances, especially in payroll configurations that trigger accrual recalculations.
Original PR description
**Steps to Reproduce:** - Install the Time Off app and Belgian Payroll (l10n_be_hr_payroll). - Create and validate an accrual allocation for currently logged-in user with: No end date Any start date…
**Steps to Reproduce:** - Install the Time Off app and Belgian Payroll (l10n_be_hr_payroll). - Create and validate an accrual allocation for currently logged-in user with: No end date Any start date An accrual plan configured with a carry-over milestone Any Time Off Type - Create another allocation for the same employee, using the same accrual plan and same Time Off Type, but with a different start date that is not in the future. - Select the accrual plan. The error is raised immediately during the onchange. **Issue:** - When the accrual allocation onchange computes the accrued balance, a temporary allocation is used internally to simulate the accrual computation. - This temporary record is discarded after the computation. - The discarded temporary record can remain pending for computed field recomputation. - When the onchange later triggers recomputation, the stale temporary NewId can cause: `KeyError: <NewId origin=18>` **Root Cause:** - Temporary allocations created with 'new(origin=allocation)' can add computed fields to `env.transaction.tocompute`. - `invalidate_recordset()` clears the temporary record's cache but does not remove the `NewId` from the pending recomputation queue. - Since the temporary record has no database row to recompute from, the NewId can later be picked up during recomputation. - This can lead to a KeyError when the framework tries to access cached data for the discarded temporary record. **Solution:** - Properly discard temporary allocations after the accrual simulation. - In addition to invalidating the cache, remove the temporary NewId from `env.transaction.tocompute` using `remove_to_compute()`. - Use this cleanup for temporary allocations created with `new(origin=...)`. **Result** - Prevents the KeyError during accrual allocation onchange. - Allows users to create another allocation with the same accrual plan without triggering the RPC error. **opw-6390559** --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285799 Forward-Port-Of: odoo/odoo#283772
Pasting a copied URL over an existing selected link in the editor no longer causes an error. This helps users edit linked text more reliably without interruptions or lost work.
Original PR description
Steps to reproduce the issue: - Create a link in editor. - Copy another URL. - Select entire link. - Pasting copied link throws traceback. This issue happens after merging commit [1] where…
Steps to reproduce the issue:
- Create a link in editor.
- Copy another URL.
- Select entire link.
- Pasting copied link throws traceback.
This issue happens after merging commit [1] where `normalize_processors` callback returns nothing. After merging commit [2] each processor must return the original root if no processing is needed or processing is in place.
As a result, when this.processThrough("normalize_processors", container) is called from the `insert` method, the next processor in the chain uses `this.editable` as its default argument and removes the FEFF node, which is the anchor node. Later calling closestBlock(selection.anchorNode) returns null, resulting in the traceback. This PR aims to fix the traceback by returning the `root` in processor.
[1]: https://github.com/odoo/odoo/commit/be77a9a2003e09f4621d0ff774bf8749b326d037
[2]: https://github.com/odoo/odoo/commit/17d58d2fdf8da3a69c731fc5ea0d90b95e28efd6
task-6456004
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283185This fix ensures mentions in social posts are correctly recognized and linked to the right profiles on Facebook, LinkedIn, and Twitter/X. It helps users publish clearer social content and avoids broken or incorrectly displayed mentions in the social posting tools.
Original PR description
This commit fixes an issue with the mention regexes for social_facebook as they weren't properly replaced by the initial mechanism. The initial mechanism was introduced by [1]. Now, we check every possible mention and if it is indeed a known mention, then we replace it by the correct link to their profile. [1]: https://github.com/odoo/enterprise/commit/4dacc5fce72687680080f75feef875fbfb3dbd15 task-6026857
This update corrects how the translation mode test module applies and removes its internal patches. It helps keep test behavior isolated so other environments or tenants are not affected after the module is uninstalled.
Original PR description
Fix patch for test_translation_mode Patch tools in a compatible way which will work for other tenants. Patch tools in a compatible way which will work after uninstallation. python code translation is not patchable by design. 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#285538
Confirmed sales orders that are locked now consistently hide product configuration edit buttons, including configurable products, event tickets, and booths. This prevents users from seeing actions that should not be available and keeps the order lock behavior consistent across sales screens.
Original PR description
### Steps to Reproduce: 1. Go to Sales > Configuration > Settings 2. Under Quotations & Orders, enable "Lock Confirmed Sales" 3. Now create a Quotation with 2 products, 1 with attributes and 1…
### Steps to Reproduce: 1. Go to Sales > Configuration > Settings 2. Under Quotations & Orders, enable "Lock Confirmed Sales" 3. Now create a Quotation with 2 products, 1 with attributes and 1 without 4. Confirm the order 5. Hover over the product with attributes and notice that it allows you to to edit, but hovering over the other product does NOT reveal the edit icon ### Issue: When a user has configured their database to lock sale orders, it should not be possible to edit the products once the order has been confirmed. It currently only happens for products that have attributes. While standard products cannot be edited in a locked state, a missing condition on configurable products allows the button to persist when hovering over the description column. This creates an inconsistent UI state where users appear to have access to modify some of the line items. ### Solution: To fix this, we updated the `hasConfigurationButton` getter in `sale_product_mixin.js` to evaluate the parent document's locked state. By adding `!this.props.record.model.root.data.locked` to the getter's return logic, the edit button is now globally hidden across all related widgets (such as `sale_label_text` and `sale_product_field`) when the sales order is locked. This ensures that configurable products properly respect the locked document restrictions just as standard products do. Additionally, this locked condition was applied to the method overrides in the `event_sale` and `event_booth_sale` modules, ensuring that event tickets and booths also hide their configuration buttons on locked orders.Additionally, this locked condition was applied to the method overrides in the event_sale and event_booth_sale modules, ensuring that event tickets and booths also hide their configuration buttons on locked orders. opw-6512288 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284882
Opening the Field Service section from a helpdesk ticket preview no longer triggers an error after completed interventions are planned. This keeps customers and staff able to view intervention information reliably from the portal preview.
Original PR description
*=helpdesk_planning_field_service{,_sale_timesheet} Steps to reproduce: ------------------------- 1. Install helpdesk_planning_field_service_sale_timesheet with demo data. 2. Open a helpdesk team…
*=helpdesk_planning_field_service{,_sale_timesheet}
Steps to reproduce:
-------------------------
1. Install helpdesk_planning_field_service_sale_timesheet with demo data.
2. Open a helpdesk team (e.g., Customer Care) and enable field service planning.
3. Create a new ticket in Customer Care, plan two interventions, and mark them as completed.
4. Click the cog menu of the helpdesk ticket and click Preview.
5. In preview mode, click **Field Service** in the left sidebar.
Issue:
---------
A traceback occurs:
```python
File "/home/odoo/odoo/community/odoo/addons/base/models/ir_qweb.py", line 875, in _render_iterall
raise QWebError(qweb_error_info) from error
odoo.addons.base.models.ir_qweb.QWebError: Error while rendering the template:
KeyError: 'format_datetime'
Template: planning_field_service.portal_my_field_service_report_list
Reference: 866
Path: /t/t/t[3]/t/tbody/t/tr/td[1]/a/t
Element: <t t-out="format_datetime(intervention.start_datetime, dt_format='MMM d, YYYY')"/>
```
Cause:
---------
https://github.com/odoo/enterprise/blob/28637781cd3ffc4c3dc0c2016dd5d6051793f641/helpdesk_planning_field_service/controllers/portal.py#L59-L63
After this 6857d1a, date formatting was changed to use `format_datetime`, and [planning_field_service](https://github.com/odoo/enterprise/blob/28637781cd3ffc4c3dc0c2016dd5d6051793f641/planning_field_service/controllers/portal.py#L42) was updated accordingly. However, `helpdesk_planning_field_service` was not updated to pass `format_datetime` in the template values, causing a **KeyError** when opening the field service intervention list.
Solution:
-----------
Pass `format_datetime` in the template values, following the same approach used in `planning_field_service`.
opw-6467400
Forward-Port-Of: odoo/enterprise#129227
Forward-Port-Of: odoo/enterprise#128519The website shop search bar placeholder will now appear in the visitor's selected website language instead of always showing "Search" in English. This improves the multilingual shopping experience and avoids confusing non-English customers.
Original PR description
Problem: The search bar placeholder text is not being translated. Steps to reproduce: 1. Install e-Commerce 2. Go to Website > Configuration and add another language for the website 3. Go to Website > Shop 4. See how the search bar placeholder text is "Search" instead of being in the website's language Cause: The text was not extracted for translation because it is set inside `t-value=`. To be available for extraction, it should either be set inside `t-valuef.translate=` or should be the data content between the tags. opw-6486429 Forward-Port-Of: odoo/odoo#285011