Daily updates from Odoo
Monday, August 3, 2026
53 changes · saas-19.4
Enhancements to existing features
The Chilean F29 tax report has been optimized to calculate all report lines in one operation, making report generation faster and more reliable. The update also refines the six-column layout, tax credit and withholding calculations, and preserves upgrade compatibility for existing installations.
Original PR description
This commit optimizes the F29 report by using just one big query to compute the data for all the report lines at once. task-4329648 Forward-Port-Of: odoo/enterprise#106701
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364 Forward-Port-Of: odoo/odoo#279925 Forward-Port-Of: odoo/odoo#278633
Original PR description
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364 Forward-Port-Of: odoo/odoo#279925 Forward-Port-Of: odoo/odoo#278633
Resolved issues and error corrections
This fixes an error that could prevent users from opening the Journal Audit report after changing and clearing the root report on the Generic Tax Report. The report now rebuilds its internal query consistently, avoiding an Internal Server Error and keeping accounting reporting accessible.
Original PR description
Step To Reproduce: - Install the Accounting module. - Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report. - Set the Root Report to "Balance Sheet" and save. - Remove the…
Step To Reproduce:
- Install the Accounting module.
- Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report.
- Set the Root Report to "Balance Sheet" and save.
- Remove the Root Report and save again.
- Open Accounting -> Reporting -> Journal Audit.
Issue:
Opening the Journal Audit report raises an Internal Server Error with: psycopg2.errors.UndefinedTable: missing FROM-clause entry for table "account_move_line__move_id"
Reason:
The code that recreates the missing "account.move" join was not updated consistently with the other "_join()" usages. Without calling "._sudo()", the ORM builds the join using a filtered subquery (for example, adding the company filter), which changes the generated join alias(https://github.com/odoo/odoo/blob/saas-19.1/odoo/orm/fields_relational.py#L559). The SQL query still references the regular alias (account_move_line__move_id), causing the query to fail.
Reference PR:- https://github.com/odoo/enterprise/pull/101230
Solution:
Use "query.table._sudo()._join()" when recreating the missing "account.move" join, matching the other "_join()" usages and ensuring the expected join alias is generated.
before fix:-
`'account_move_line__move_id__2': (SQL('JOIN'), SQL('(SELECT "account_move".* FROM "account_move" WHERE "account_move"."company_id" IN %s)', (1,)), SQL('"account_move_line"."move_id" = "account_move_line__move_id__2"."id"'))`
Query : `JOIN (
SELECT
account_move.*
FROM account_move
WHERE account_move.company_id IN (1)
) AS account_move_line__move_id__2
ON account_move_line.move_id = account_move_line__move_id__2.id`
after fix:-
`'account_move_line__move_id': (SQL('JOIN'), SQL('"account_move"'), SQL('"account_move_line"."move_id" = "account_move_line__move_id"."id"'))`
Query : `JOIN account_move AS account_move_line__move_id
ON account_move_line.move_id = account_move_line__move_id.id`
opw-6425842
Forward-Port-Of: odoo/enterprise#125968The Timesheets overtime indicator now shows remaining time in the selected unit even when users switch languages. This prevents confusion for multilingual teams using day or half-day timesheet entry, where values could previously appear as hours instead of days.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133 Forward-Port-Of: odoo/enterprise#126256 Forward-Port-Of: odoo/enterprise#120595
Swiss payroll calculations now use consistent rounding to the nearest 0.05 instead of combining cent rounding with manual adjustments. This prevents tiny rounding differences from incorrectly appearing in salary declarations, improving payroll accuracy and test reliability.
Original PR description
In multiple places within l10n_ch_hr_payroll_elm we use float_round to a precision of 0.01 but then manually round to 0.05 precision. 1. Open a python terminal 2. Enter 1000 % 0.05 >= 0.025 3. See this results to true, even though it shouldn't Fix this by using float_round with a precision of 0.05 instead. https://github.com/odoo/enterprise/blob/7f9cd01ff3dd470b06ae176982fd042243be8f3c/l10n_ch_hr_payroll_elm/models/hr_payslip.py#L102-L105 The change to `ema_declaration.json` is needed as previously it was expected that there was a small difference between salary over the months due to the odd rounding (a difference of like 0.000000000001). Adding the new rounding makes the values equal and test_ema_declaration_2023_01 would fail due to changeSalary no longer being in the computed dict. All the way to master! opw-6322937 Forward-Port-Of: odoo/enterprise#121401
In single-company setups, users could not change the journal on depreciation models when no company was set because the company selector was hidden and the visible journal field was read-only. The update keeps the company field available and removes an unnecessary warning in single-company environments, making depreciation model setup editable again.
Original PR description
When no company is set on a depreciation model, we only display the `journal_placeholder_id` field which is readonly. But in a single company environment, the 'company_id` field is hidden, therefore it becames impossible to change the journal for depreciation models. Fix: Always display the `company_id` field, but we remove the warning in the onchange when we are in a single company environment. opw-6299390 Forward-Port-Of: odoo/enterprise#121518
Users can now click custom fields in the Documents list view and edit them directly, without first activating another standard field. This makes customized document workflows smoother and avoids a confusing extra step for teams using Studio-created fields.
Original PR description
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The…
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The user has to first click a standard editable field (like "Owner") to put the row into edit mode before they can modify the custom field. This occurs because we use a hardcoded whitelist (`editableColumns`) of standard fields allowed to trigger edit mode. Custom fields (`x_`) are missing from this static list. This commit resolves the issue by dynamically injecting visible, non-readonly custom fields into the `editableColumns` whitelist. This allows user-created fields to be edited inline as expected. **Steps to reproduce:** - Documents > Studio > List view > Add any field that accepts user input (e.g. Text/char) > save/exit - In the same Documents list view > select a row > click the cell belonging to the newly created field > observe that the row does not enter edit mode - In the same Documents list view > select a row > click a standard editable cell, then click the cell belonging to our newly created field > observe that this then allows us to edit our field **Current behavior before PR:** - Custom fields do not trigger inline edit mode **Desired behavior after PR is merged:** - Custom fields trigger inline edit mode opw-6378102 Forward-Port-Of: odoo/enterprise#125378 Forward-Port-Of: odoo/enterprise#125239
This fixes an issue in Mexican payroll where removing a payslip start or end date could cause an error. Users can now edit or clear payslip dates without the form crashing, improving reliability during payroll preparation.
Original PR description
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI`…
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI` company - Go to `Payslips`, create a payslip. - Set an `employee`, and remove either the `start date` or the `end date` from Period.. `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` After the [recent commit] adding a warning about the employee exceeding the salary limit, when the user removes the dates from the payslip, the compute method attempts to compute the warning from [1], and when it adds relativedelta to date_from, which is False, it raises the error [2]. This commit ensures that the payslip dates are checked first before adding relativedelta to the date and performing the comparison. [recent commit]: https://github.com/odoo/enterprise/commit/6abfa47dafe439f9328d606ef6ac5126ec6eb1f6 [1]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/hr_payroll/models/hr_payslip.py#L1446 [2]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py#L272-L276 Forward-Port-Of: odoo/enterprise#125479 Forward-Port-Of: odoo/enterprise#122643
Fixed an issue that could cause the field service planning map to crash when opening the routing popup for groups with unassigned or mixed resources. The popup now appears only when the selected group consistently matches the records' resources, making the experience more reliable across languages and planning setups.
Original PR description
This commit fixes an issue where we search the resources' types in a group's records, possibly not having any resource. Prior to this commit, a condition filtered out the "None" group. However, this causes three issues: 1. The condition does not consider translations (so this would fail for the "None" group in French for instance); 2. If there is any other group than Open Shifts not having resources, this would fail. 3. If there is another group that does not belong to a resource or to Open Shifts that has some records without resources, we should not display the popup. Instead, we dynamically check whether the groupId is part of the resource_ids of *every* group's record in order to display the popup. no-task
The Timesheet Assistant no longer suggests calendar events marked as available. This keeps recommendations focused on events that can actually be timesheeted and helps users avoid irrelevant entries.
Original PR description
## Previous Behavior In the Timesheet Assistant view, calendar events marked as *available* were still being suggested. These events are not intended to be timesheeted and should not appear in the assistant’s recommendations. Their presence could also obscure more relevant events that require user attention. ## New Expected Behavior Calendar events marked as *available* are now excluded from Timesheet Assistant suggestions. task-[6431591](https://www.odoo.com/odoo/project/4105/tasks/6431591) Forward-Port-Of: odoo/enterprise#126183
Users can now resize scheduled work orders in the Gantt planning view without triggering an error. The fix makes schedule updates more reliable, especially when work orders depend on each other.
Original PR description
## Problem When dragging the edge of a scheduled workorder to change the start or end time, _web_gantt_move_candidates would throw a traceback. This is because the web call only supplies the new time…
## Problem When dragging the edge of a scheduled workorder to change the start or end time, _web_gantt_move_candidates would throw a traceback. This is because the web call only supplies the new time chosen by the drag+drop. That is, if date_end was changed, date_start wouldn't be present, so accessing the missing field directly triggers a KeyError. This also revealed a secondary issue involving dependent tasks, where if the parent task is rescheduled with the pills, the child task would fail to find candidate reschedule dates (since its only dependency is being moved), and no boundary date would be supplied when calling _web_gantt_reschedule_compute_dates. This led to another traceback. ## Solution For the first issue, we will get the start date and end date from the supplied values more safely, using get() to default to the original start/end. For the second issue, if the boundary date isn't found by _web_gantt_get_first_and_last_possible_dates, we fall back to the candidate's existing start or end date. ## Steps to replicate (Runbot saas-19.4) 1. Create a product with a BOM with 2 operations on the same workcenter 2. Create an MO for this product, confirm it, and plan it 3. Head to Manufacturing > Planning > Work Orders / Planning 4. Try to change the end date of the first work order by dragging the edge of the pill opw-6378769
This fix makes the Swedish point of sale test consistently create its order before finishing. It reduces random test failures, helping keep validation of Swedish POS behavior stable without changing customer-facing functionality.
Original PR description
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing:…
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing: https://github.com/odoo/enterprise/blob/0f6f6fac892bc8cec477160a790d52fbf053be99/l10n_se_pos/tests/test_se_pos.py#L40-L42 ## Steps to reproduce 1. Install `l10n_se_pos` 2. Run the test `test_l10n_se_pos_01` 3. **The test fails non-deterministically** ## Fix We use `clickNextOrder()` at the end of the tour to ensure the creation of the order, like other tests already do (e.g., [FinishResidualOrder](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L676-L677), [test_name_preset_skip_screen](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L1333-L1334), [PosOrderCreationTourPdis](https://github.com/odoo/enterprise/blob/08d5172a8c3310af0c51e18a281c544f83f5aed7/pos_enterprise/static/tests/tours/point_of_sale/pos_tour.js#L141-L142), ...). runbot-238568 Forward-Port-Of: odoo/enterprise#125672
This fix ensures Swiss payroll automatically calculates salary code 2050 during payroll processing. It reduces manual work and helps produce more accurate Swissdec payroll reporting.
Original PR description
task-5166226 Forward-Port-Of: odoo/enterprise#114650 Forward-Port-Of: odoo/enterprise#103453
Guatemalan invoice PDFs now show the same customer tax identifier used in the official electronic XML, including using “CF” when no valid VAT is available. The legal 2,500 threshold is also checked in the company currency, helping avoid inconsistent compliance results on foreign-currency invoices.
Original PR description
with this commit:- - Display 'CF' in the invoice PDF whenever the generated XML uses CF. - Treat placeholder VAT values such as '/', 'NA', and 'na' as missing VAT. - Compare the invoice total using the company currency instead of the document currency when evaluating the 2,500 threshold, ensuring the legal limit is applied consistently regardless of the invoice currency task-6305333 Forward-Port-Of: odoo/enterprise#120985
The Stripe expense cardholder field now follows the correct setup method, ensuring filters from the form are applied as expected. This helps users see the right selectable cardholders and prevents incorrect or confusing choices when managing expenses.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Forward-Port-Of: odoo/enterprise#125346
A Timesheet Grid rule was adjusted so notification counts in Discuss are ignored when matching messages. This prevents false matches and helps timesheet-related automation behave consistently when users have unread notifications.
Original PR description
task: 6416889 Forward-Port-Of: odoo/enterprise#125877 Forward-Port-Of: odoo/enterprise#125519
The automated tests for assigning resources in Planning Field Service were made more reliable by avoiding a timing issue in the resource selection step. This reduces false test failures and helps keep development and release checks stable without changing user-facing behavior.
Original PR description
This commit fixes undeterministic failures in the `many2many_avatar_resource` tests. Previously, resources were added by typing its name, waiting for the list to update and clicking on the resource. However, `edit` auto-completes with some delay, thereby resulting in random errors where the first resource from the list was added. Instead, we let the `edit` autocomplete to run in order to add a resource, ensuring the first resource from the list is not added as a consequence. runbot-error-941174
Customers can no longer complete checkout for planning-based rental services when the requested time slot has no available resources. The cart now warns and blocks payment until the customer chooses an available date or reduces the quantity, preventing paid orders that cannot be fulfilled.
Original PR description
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The…
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The cart lets them increase the quantity past the available capacity and proceed all the way through checkout without any availability gate. **Steps to reproduce:** 1. Install `website_sale_renting_planning`. 2. Create a planning role with `sync_shift_rental` and one resource. 3. Create a service product with `rent_ok=True`, `planning_enabled=True` and the role above. 4. Pre-book the resource for some window via a `planning.slot`. 5. From eCommerce, add the product to the cart for the same window. 6. Proceed to checkout/payment. **Current behavior:** The cart is considered ready, no warning is shown, and payment can proceed even though no planning resource is free for the chosen period. **Expected behavior:** The cart should be flagged as not ready and pre-payment validation should refuse to confirm until the customer picks a different date or quantity. **Cause of the issue:** `sale.order._available_dates_for_renting` in `website_sale_renting` is the documented hook for "stock availability" gating of the cart and pre-payment flow (called from `_is_cart_ready` and from `_check_cart_is_ready_to_be_paid`). `website_sale_stock_renting` overrides it to apply a per-line stock check, but `website_sale_renting_planning` has no such override, so planning-backed rental services reach payment with no availability gate at all. **Fix:** Apply the same gating pattern that `website_sale_stock_renting` already uses: override `_available_dates_for_renting` in `website_sale_renting_planning` so that, for each rental line whose product is a planning-synced rentable service, the cart is only considered valid when at least the requested quantity of planning resources is free during the rental window (mirroring the resource and leave filtering already done by `_planning_slot_vals_list_per_sol` at SO confirmation time). This puts the gate at the same point the stock-renting flow enforces it, keeping the public cart/checkout flow consistent across rentable product types. opw-6247034 Forward-Port-Of: odoo/enterprise#125732 Forward-Port-Of: odoo/enterprise#118943
Before this commit: - The `routing_identifier` field was reset on save because `_get_all_identifiers` checked it prematurely before `routing_scheme` and `routing_endpoint` were stored. - Fixing this exposed a French PDP test failure: the test expected `routing_identifier` to stay empty when entering a SIREN, which previously passed only due to the reset bug. After this commit: - `_get_all_identifiers` checks scheme and endpoint directly so `routing_identifier` persists properly on save. -
Original PR description
Before this commit: - The `routing_identifier` field was reset on save because `_get_all_identifiers` checked it prematurely before `routing_scheme` and `routing_endpoint` were stored. - Fixing this exposed a French PDP test failure: the test expected `routing_identifier` to stay empty when entering a SIREN, which previously passed only due to the reset bug. After this commit: - `_get_all_identifiers` checks scheme and endpoint directly so `routing_identifier` persists properly on save. - French PDP suggests SIREN for lookups without auto-filling `routing_identifier` on partner creation. - Removed an unused line in tests. > These fixes were discussed and confirmed with @clbr-odoo no-task
Running more than one gevent worker relies on every worker binding the same address, which the kernel only allows when SO_REUSEPORT is set on the socket before bind(2). The regression was introduced by 17164382feeeb3d081aabe398442f8a8f319e507, which replaced the hand-rolled socket setup with socket.create_server. That helper binds and listens on the spot, so the option was left applying to an already bound socket, where it does nothing. Only the prefork master spawns those processes, so i
Original PR description
Running more than one gevent worker relies on every worker binding the same address, which the kernel only allows when SO_REUSEPORT is set on the socket before bind(2). The regression was introduced…
Running more than one gevent worker relies on every worker binding the same address, which the kernel only allows when SO_REUSEPORT is set on the socket before bind(2). The regression was introduced by 17164382feeeb3d081aabe398442f8a8f319e507, which replaced the hand-rolled socket setup with socket.create_server. That helper binds and listens on the spot, so the option was left applying to an already bound socket, where it does nothing. Only the prefork master spawns those processes, so it takes --workers together with more than one gevent worker for the breakage to show. When it does show, the first worker binds the gevent port and the others exit with EADDRINUSE, only to be respawned in a loop by the master. create_server already applies the option between socket creation and bind when asked for it, so let it do so. 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
Steps to produce: --- - Install the Sales module. - Enable `Pricelists` from Sales settings. - Create a new product. - Go to Sales > Products > Pricelists and open an existing pricelist. - Add the following rules for a product: - min qty: 1 > price: 100 - min qty:10 > price: 80 - Create a new quotation > add section > add the same product. - Set the section as optional > Preview the quotation. - Change its quantity to 10. Added test covering the fix introduced in [com
Original PR description
Steps to produce:
---
- Install the Sales module.
- Enable `Pricelists` from Sales settings.
- Create a new product.
- Go to Sales > Products > Pricelists and open an existing pricelist.
- Add the following rules for a product:
- min qty: 1 > price: 100
- min qty:10 > price: 80
- Create a new quotation > add section > add the same product.
- Set the section as optional > Preview the quotation.
- Change its quantity to 10.
Added test covering the fix introduced in [commit], ensuring
that pricelist rules are correctly reapplied when the quantity of an
optional product is changed from the quotation preview.
[commit]: https://github.com/odoo/odoo/commit/93b6bdd6a4909bc0b45b90ab6a2d0734a218292d
opw-6241183
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279135
Forward-Port-Of: odoo/odoo#266597Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `mrp` module - Go to the setting enable `Lots & Serial Numbers` and `Storage Locations` - Create a storable product tracked by Lots - Configure a Putaway Rule for the product so it is stored in a sub-location - Create a Bill of Materials for the product with at least one component - Create and confirm a Manufacturing Order - Increase the production quantity (e.g. using the "Change Production Quantit
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `mrp` module - Go to the setting enable `Lots & Serial Numbers` and `Storage Locations` - Create a storable product tracked…
Version:
--------
- 19.0+
Steps to reproduce:
-------------------
- Install `mrp` module
- Go to the setting enable `Lots & Serial Numbers` and `Storage Locations`
- Create a storable product tracked by Lots
- Configure a Putaway Rule for the product so it is stored in a
sub-location
- Create a Bill of Materials for the product with at least one
component
- Create and confirm a Manufacturing Order
- Increase the production quantity (e.g. using the "Change Production
Quantity" wizard)
- Click **Generate Lot/Serial Number**
- Click **Produce All**
Issue:
------
Completing the Manufacturing Order raises:
Invalid Operation
You need to supply a Lot/Serial Number for product:
- Product
even though a single lot should be sufficient for a lot-tracked
product.
Cause:
------
When the production quantity is increased, `change_prod_qty()` updates
the finished move's demanded quantity and re-reserves it through
`_update_finished_moves()`:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/mrp/wizard/change_production_qty.py#L77
which calls `_action_assign()` on the finished move:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/mrp/wizard/change_production_qty.py#L49
Since finished moves originate from the production location, they
bypass the normal reservation flow:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/stock/models/stock_move.py#L2070
`_action_assign()` then tries to reuse the move's existing move line,
but the lookup requires `location_dest_id` to still match the move's
generic destination:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/stock/models/stock_move.py#L2092-L2106
That existing line's `location_dest_id` was already redirected to the
putaway sub-location by the previous `_apply_putaway_strategy()` call
(at MO confirmation), so the lookup no longer matches and a second,
distinct move line is created and appended instead of the first one
being reused:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/stock/models/stock_move.py#L2170
Later, clicking **Generate Lot/Serial Number** creates a single lot and
stores it on the production order's `lot_producing_ids`:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/mrp/models/mrp_production.py#L1602
When **Produce All** is clicked, which trigger `button_mark_done()` it calls
`_post_inventory()`:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/mrp/models/mrp_production.py#L2227
which assigns that lot to the finished move through `move.lot_ids`:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/mrp/models/mrp_production.py#L1925
Since `lot_ids` is declared with `inverse='_set_lot_ids'`, this write
triggers that inverse method:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/stock/models/stock_move.py#L192
The current implementation of `_set_lot_ids()` only assigns the lot to
a single available move line, regardless of tracking type:
https://github.com/odoo/odoo/blob/154b49ec6be6230989ee4eb420e7f83b681ff520/addons/stock/models/stock_move.py#L656-L668
Since only one lot is ever generated for a lot-tracked product, only
the first finished move line receives a `lot_id`. The second move line
created after increasing the production quantity is left without one.
When `button_mark_done()` validates the finished move lines, it
detects that one of them still has no lot assigned and raises the
"Invalid Operation" error, even though a single lot is valid for the
entire production of a lot-tracked product.
Fix:
----
`action_generate_serial` produces a single lot for the whole production.
In `_post_inventory()`, right after the generated lot is set on
the finished move, propagate it to any remaining lot-less move lines
of a **lot**-tracked finished move.
---
opw-6366060
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277819
Forward-Port-Of: odoo/odoo#275000Description of the issue this commit addresses: The settlement tour expects an invoice named with the year 2026. On time-shifted test instances, invoices use a later year, so the tour cannot find the invoice and fails at the settlement selection step. --- Desired behavior after this commit is merged: This commit matches settlement invoices using the stable journal prefix, so the tour works regardless of the year in which it runs. --- runbot-[242206](https://runbot.odoo.com/odoo
Original PR description
Description of the issue this commit addresses: The settlement tour expects an invoice named with the year 2026. On time-shifted test instances, invoices use a later year, so the tour cannot find the invoice and fails at the settlement selection step. --- Desired behavior after this commit is merged: This commit matches settlement invoices using the stable journal prefix, so the tour works regardless of the year in which it runs. --- runbot-[242206](https://runbot.odoo.com/odoo/error/242206) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279756 Forward-Port-Of: odoo/odoo#278573
account/tests/test_audit_trail.py::TestAuditTrail.test_content was failing whenever l10n_fr_pdp was installed: posting/resetting a move produced an extra "E-Reporting Status" tracking value on top of the expected name/state ones. l10n_fr_pdp_status and l10n_fr_pdp_last_flow_id are tracked fields but are meant to be excluded from generic tracking and reported via a dedicated chatter message instead. The exclusion was implemented by overriding _message_track(), a method that no longer exi
Original PR description
account/tests/test_audit_trail.py::TestAuditTrail.test_content was failing whenever l10n_fr_pdp was installed: posting/resetting a move produced an extra "E-Reporting Status" tracking value on top of the expected name/state ones. l10n_fr_pdp_status and l10n_fr_pdp_last_flow_id are tracked fields but are meant to be excluded from generic tracking and reported via a dedicated chatter message instead. The exclusion was implemented by overriding _message_track(), a method that no longer exists in the mail tracking API (replaced by _track_get_fields()/_track_prepare() some time ago), so the override was dead code and never ran. Override _track_get_fields() instead, which is the actual hook the framework uses to build the set of auto-tracked fields. runbot error - 941346 Forward-Port-Of: odoo/odoo#278095
Forward-Port-Of: odoo/odoo#279378
Original PR description
Forward-Port-Of: odoo/odoo#279378
Steps: - Install marketing_card & website_event_track - Create a marketing card campaign for "Event Track" - Create an event with tracks - Click on "Send Cards" in event form - Choose your campaign for the mailing - Update X cards for the mailing Actual result: - Recipients is "Event Track" - Card Campaign Mailing should target model Event Track - Mailing model is still the default one during the validation Expected result: - No error - Card are updated - User will be able to s
Original PR description
Steps: - Install marketing_card & website_event_track - Create a marketing card campaign for "Event Track" - Create an event with tracks - Click on "Send Cards" in event form - Choose your campaign for the mailing - Update X cards for the mailing Actual result: - Recipients is "Event Track" - Card Campaign Mailing should target model Event Track - Mailing model is still the default one during the validation Expected result: - No error - Card are updated - User will be able to send mailing after update Forward-Port-Of: odoo/odoo#279288
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment should be enabled from the settings to proceed) 3. Once the transaction is processed and the order confirmed, check the confirmation email/PDF sent to the customer in the chatter **Issue:** - The order confirmation sent to the customer after paying online does not include the signature they provide
Original PR description
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment…
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment should be enabled from the settings to proceed) 3. Once the transaction is processed and the order confirmed, check the confirmation email/PDF sent to the customer in the chatter **Issue:** - The order confirmation sent to the customer after paying online does not include the signature they provided when accepting the quotation - Even if "Online Payment" is not enabled and Signing will directly confirm the order, the signature is still missing. **Why this happens:** - The signature block in `sale.report_saleorder_document` is gated by the `sale_include_signature` context key rather than solely by doc.signature. This was introduced by commit ef8246a4daf6146da2ed3cb78c37c7bf0937a4df to retain signature integrity. - `portal_quote_accept` only sets this context right after the customer signs on the pdf rendered for us (company), and was not passed through `_validate_order()` when there was no online payment - When online payment is required, `_has_to_be_paid()` defers the order confirmation which happens later, and the context is never set elsewhere **Fix:** - Pass the context when online payment is not required - If online payment is required, the sale quotation can be modified after being signed. However, since the customer previews the quotation when Paying, we can say the signature integrity is retained opw-6389733 Forward-Port-Of: odoo/odoo#278854
Current behavior before PR ----- The "unit cost" footer line was showing up on each page of the bom overview, overlapping with other lines. Desired behavior after PR is merged ----- The "unit cost" footer line should only appear at the bottom of the overview. Forward-Port-Of: odoo/odoo#262995
Original PR description
Current behavior before PR ----- The "unit cost" footer line was showing up on each page of the bom overview, overlapping with other lines. Desired behavior after PR is merged ----- The "unit cost" footer line should only appear at the bottom of the overview. Forward-Port-Of: odoo/odoo#262995
Steps to reproduce: - Install `project`, open a project and switch to the Gantt view - Start dragging a task while holding Ctrl (copy mode), then switch browser tab with Ctrl+Tab (or Ctrl+Shift+Tab, Ctrl+PgUp/PgDn) - Come back to the Gantt tab and drop the task without holding Ctrl Issue: The task is duplicated instead of rescheduled. Cause: The copy/reschedule behavior is tracked through window keydown/keyup listeners on the Control key. While the document is hidden, the keyup for Co
Original PR description
Steps to reproduce: - Install `project`, open a project and switch to the Gantt view - Start dragging a task while holding Ctrl (copy mode), then switch browser tab with Ctrl+Tab (or Ctrl+Shift+Tab,…
Steps to reproduce: - Install `project`, open a project and switch to the Gantt view - Start dragging a task while holding Ctrl (copy mode), then switch browser tab with Ctrl+Tab (or Ctrl+Shift+Tab, Ctrl+PgUp/PgDn) - Come back to the Gantt tab and drop the task without holding Ctrl Issue: The task is duplicated instead of rescheduled. Cause: The copy/reschedule behavior is tracked through window keydown/keyup listeners on the Control key. While the document is hidden, the keyup for Control is never received, so the drag sequence resumes with a stale "Ctrl pressed" state and the drop is treated as a copy. Fix: Keyboard and pointer states cannot be reliably tracked while the document is hidden, so cancel any ongoing drag sequence from `makeDraggableHook` as soon as the tab is no longer visible (through the `visibilitychange` event). This applies to every drag and drop instance built on the hook builder. opw-6298440 Forward-Port-Of: odoo/odoo#277014 Forward-Port-Of: odoo/odoo#276859
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: ---
Original PR description
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 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#277748 Forward-Port-Of: odoo/odoo#277180
When selling a product with the Ship Later option the COGS for the product were not recorded properly. Steps to reproduce: ------------------- * Create a product with fifo and real_time valuation * Open PoS and add the product to the order * Validate the order and set the Ship Later option * Go to the backend and validate the picking of the order * Go check the journal entries of the session > Observation: It doesn't contain the COGS line. Why the fix: ------------ Since the stock
Original PR description
When selling a product with the Ship Later option the COGS for the product were not recorded properly. Steps to reproduce: ------------------- * Create a product with fifo and real_time valuation * Open PoS and add the product to the order * Validate the order and set the Ship Later option * Go to the backend and validate the picking of the order * Go check the journal entries of the session > Observation: It doesn't contain the COGS line. Why the fix: ------------ Since the stock_valuation refactoring the COGS are not created anymore when validating the picking of the order. opw-5965021 Forward-Port-Of: odoo/odoo#278308 Forward-Port-Of: odoo/odoo#259714
The navigator class, which adds event handlers, is instanciated on the setup of components using the useNavigation hook. However, before this commit, it was destroyed when the components were unmounted. It may happen that components are instanciated (setup is executed) but never mounted in the DOM, when the current rendering is cancelled. When this happened, the navigator cleanup wasn't executed, resulting in a small memory leak. This commit fixes the issue by using onWillDestroy instead.
Original PR description
The navigator class, which adds event handlers, is instanciated on the setup of components using the useNavigation hook. However, before this commit, it was destroyed when the components were unmounted. It may happen that components are instanciated (setup is executed) but never mounted in the DOM, when the current rendering is cancelled. When this happened, the navigator cleanup wasn't executed, resulting in a small memory leak. This commit fixes the issue by using onWillDestroy instead. 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#279657 Forward-Port-Of: odoo/odoo#279322
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill Error from the portal: `[372] Invalid or Blank Consignee Ship-to State Code` It is currently a flaw in the government portal because in Government portal there is no option for the Other country (99) for Ship to state code and only option for Other Teritory(97) It is because in reality, i
Original PR description
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill…
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill Error from the portal: `[372] Invalid or Blank Consignee Ship-to State Code` It is currently a flaw in the government portal because in Government portal there is no option for the Other country (99) for Ship to state code and only option for Other Teritory(97) It is because in reality, it should the port ship to state code but there cases where goods can be transfered to nearby country i.e. Bangladesh, Nepal where good can taken by road from India In that case the state code should be 97 task-6431082 **Second Commit** - [FIX] l10n_in_ewaybill: import/export GSTIN should be URP Steps to reproduce: Use the real testing credentials Create a SEZ partner Create an invoice and ewaybill Select the type of Ewaybill as Export Tax Invoice We get error code-450 which clearly states, `450 For outward-export ewaybill, To GSTIN has to be either URP or SEZ` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279289
Before this commit, the composer suggestion list could re-open right after the user closed it with Escape, and the next press of Escape would then close the list again instead of being handled by the composer (e.g. discarding a reply). This happened because NavigableList was re-opened on every patch: the useEffect opening the list had `[this.props]` as dependency, and props are a new object on every render. Any unrelated re-render of the composer (e.g. triggered by a late store update) would
Original PR description
Before this commit, the composer suggestion list could re-open right after the user closed it with Escape, and the next press of Escape would then close the list again instead of being handled by the composer (e.g. discarding a reply). This happened because NavigableList was re-opened on every patch: the useEffect opening the list had `[this.props]` as dependency, and props are a new object on every render. Any unrelated re-render of the composer (e.g. triggered by a late store update) would therefore re-open the list, which would then steal the next Escape from the composer. Fix by narrowing the dependency to the content of the options, so the list only opens on mount and when a new set of options arrives. https://runbot.odoo.com/odoo/error/944571 Forward-Port-Of: odoo/odoo#279498 Forward-Port-Of: odoo/odoo#278929
The daily/monthly Inventory Valuation Closing cron currently skips companies using the Perpetual (real_time) valuation method, so the Periodic Valuation frequency setting has no effect for them. The intent of the feature is to keep the inventory valuation continuously updated (e.g. goods received not yet invoiced) whatever the valuation method, so the cron should also post the closing entries for perpetual companies. Remove the real_time exclusion from the cron domain so the configured frequency
Original PR description
The daily/monthly Inventory Valuation Closing cron currently skips companies using the Perpetual (real_time) valuation method, so the Periodic Valuation frequency setting has no effect for them. The intent of the feature is to keep the inventory valuation continuously updated (e.g. goods received not yet invoiced) whatever the valuation method, so the cron should also post the closing entries for perpetual companies. Remove the real_time exclusion from the cron domain so the configured frequency applies to all companies, and skip companies where the closing raises a UserError (e.g. missing valuation journal or account) so one misconfigured company cannot block the cron. Forward-Port-Of: odoo/odoo#278618 Forward-Port-Of: odoo/odoo#276990
Make sure to click on the correct action menu when tryin to delete the selected website page. If we do not specify this we could randomly click on the little gear menu that do not contain the delete option. It's actually already done like this in 19.3 here https://github.com/odoo/odoo/blob/c5d7a6a90be4730e18070826a9394ab10dfc6be8/addons/website/static/tests/tours/page_manager.js#L129 runbot-233357 Forward-Port-Of: odoo/odoo#278503 Forward-Port-Of: odoo/odoo#276897
Original PR description
Make sure to click on the correct action menu when tryin to delete the selected website page. If we do not specify this we could randomly click on the little gear menu that do not contain the delete option. It's actually already done like this in 19.3 here https://github.com/odoo/odoo/blob/c5d7a6a90be4730e18070826a9394ab10dfc6be8/addons/website/static/tests/tours/page_manager.js#L129 runbot-233357 Forward-Port-Of: odoo/odoo#278503 Forward-Port-Of: odoo/odoo#276897
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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.odo
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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#278123
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the BOM's form view. 4) Configure the first sequential operation to be blocked by the second 5) Make and confirm an MO using this BOM 6) Uncheck "Operation Dependencies" on the BOM 7) Press "Plan" on the MO, a validation error is thrown stating "You cannot create cyclic dependency." Issue occur
Original PR description
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the…
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the BOM's form view. 4) Configure the first sequential operation to be blocked by the second 5) Make and confirm an MO using this BOM 6) Uncheck "Operation Dependencies" on the BOM 7) Press "Plan" on the MO, a validation error is thrown stating "You cannot create cyclic dependency." Issue occurs because after the MO is confirmed the blocked_by_workorder_ids field for mrp.workorder records is set based on the order manually configured on the BOM (operation 1 is blocked by operation 2). After the BOM is edited to have allow_operation_dependencies = false, then Odoo uses the default sequential ordering when planning the operations (operation 2 is blocked by operation 1). Since the old ordering is never cleared, a cycle is created unintentionally. This PR resolves this issue by clearing the blocked_by_workorder_ids field on mrp.workorder records. opw-6334271 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278706 Forward-Port-Of: odoo/odoo#275154
In the `render_task_templates` branch, the `has_template_ancestor` step called `.toList({})`, turning `domain` into a plain list. It was only rebuilt into a `Domain` when a `default_project_id` was in context, so otherwise the trailing `domain.toList({})` threw `TypeError: domain.toList is not a function`. Introduced in 694ea6a2fb60 (odoo/odoo#279015). Fix: drop the premature `.toList({})` so `domain` stays a `Domain` until the single final conversion. Appeared on many clickAll failures
Original PR description
In the `render_task_templates` branch, the `has_template_ancestor` step called `.toList({})`, turning `domain` into a plain list. It was only rebuilt into a `Domain` when a `default_project_id` was in context, so otherwise the trailing `domain.toList({})` threw `TypeError: domain.toList is not a function`.
Introduced in 694ea6a2fb60 (odoo/odoo#279015).
Fix: drop the premature `.toList({})` so `domain` stays a `Domain` until the single final conversion.
Appeared on many clickAll failures assigned to the JS team:
https://runbot.odoo.com/odoo/error/944607## Problem When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total. ## Solution When retreiving the relevant moves for quantity calculation (_get_outgoing_incoming_moves), we will filter out any moves not belonging to the SOL's company. This will prevent moves from other companies into the interco location from being counted towards qty_delivered. ## Steps to Replicate (runbot v19) 1. Create a route
Original PR description
## Problem When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total. ## Solution When retreiving the relevant moves…
## Problem
When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total.
## Solution
When retreiving the relevant moves for quantity calculation (_get_outgoing_incoming_moves), we will filter out any moves not belonging to the SOL's company. This will prevent moves from other companies into the interco location from being counted towards qty_delivered.
## Steps to Replicate (runbot v19)
1. Create a route
- Pull Comp B -> Interco, MTO, Comp B delivery
- Pull Interco -> Comp A, MTS, Comp A receipt
(You can review the test for more info about this route config)
(There is also this video showcasing the issue on runbot: https://drive.google.com/file/d/1YeUie4EhWPyg_RuJkNf40S9zARB4jXWY/view)
2. Attach a product to this new route
3. Create a SO for the product and confirm it
4. You should see 4 pickings, validate the chain
5. The qty_delivered on the sale order is double the demand
opw-6361559
Forward-Port-Of: odoo/odoo#275694## Issue In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager. ## Steps to reproduce 1. Install *Attendances* (`hr_attendance`) 2. In Settings: - Toggle *Attendances from Backend* - Toggle *Absence Management* - Toggle *Display Extra Hours* - Set *Extra Hours Validation* to *Approved by Manager* 3. On an Employee E: - Overtime Ruleset: Default Ruleset 4. In Attendances, create an attendance for emplo
Original PR description
## Issue In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager. ## Steps to reproduce 1. Install *Attendances* (`hr_attendance`) 2. In…
## Issue
In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager.
## Steps to reproduce
1. Install *Attendances* (`hr_attendance`)
2. In Settings:
- Toggle *Attendances from Backend*
- Toggle *Absence Management*
- Toggle *Display Extra Hours*
- Set *Extra Hours Validation* to *Approved by Manager*
3. On an Employee E:
- Overtime Ruleset: Default Ruleset
4. In Attendances, create an attendance for employee E on a day where they are expected to work. The attendance should be shorter than a full day of work (e.g., from 9:00am to 11:00am, which would be -6 hours of overtime if 8 hors are expected).
5. Navigate to Attendances > Management
6. **The attendance created in Step 4 does not appear, even though it should be approved by a manager.**
## Cause
The domain for the `hr_attendance_management_action` is the following:
https://github.com/odoo/odoo/blob/22a94663e4c1672366b7a614943cef843ced3503/addons/hr_attendance/views/hr_attendance_view.xml#L439
The `overtime_hours > 0` condition was added by https://github.com/odoo/odoo/commit/e5067262174725466056e9a6c530439b4845c19b with the intent to remove attendance records with zero extra hours. Instead, it removes all records with less than zero extra hours.
opw-6372360
Forward-Port-Of: odoo/odoo#275643In saas-19.3, a new calendar view was added for the "Monthly Hours" smart button on an Employee record. A test was added to test the flow of creating a time off request through this view. In this test, we attempt to switch to the calendar view. However, in community tests, this was failing as there is no view switcher here. In an enterprise database, you have the option to switch to a Gantt view, so the view switcher will show up. However, this does not exist in community. To remedy this, we sho
Original PR description
In saas-19.3, a new calendar view was added for the "Monthly Hours" smart button on an Employee record. A test was added to test the flow of creating a time off request through this view. In this test, we attempt to switch to the calendar view. However, in community tests, this was failing as there is no view switcher here. In an enterprise database, you have the option to switch to a Gantt view, so the view switcher will show up. However, this does not exist in community. To remedy this, we should ensure that we're in an environment where the view switcher exists first, before trying to change to the calendar view. [runbot-941240](https://runbot.odoo.com/odoo/error/941240?debug=assets) Forward-Port-Of: odoo/odoo#279816
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with n
Original PR description
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry…
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with no socket, no listeners and no pending timeout: it never reconnects. Schedule the reconnection when handling a manually triggered close, since no error event will follow to do it. [1]: https://github.com/odoo/odoo/pull/278075 runbot-944578 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#279046 Forward-Port-Of: odoo/odoo#278779
### Steps to reproduce: - Enable developer mode - Go to Settings > Technical > Messages > ValueError: Cannot search, too many messages ### Cause of Issue: The new `ir.access` model introduced through https://github.com/odoo/odoo/pull/166359 inherits from `mail.thread` and enables tracking on the `active`, `domain`, and `operation` fields. https://github.com/odoo/odoo/blob/713f68333798575d70362cbb55ca31e91e75d5fa/addons/mail/models/ir_access.py#L7-L12 In production databases, every acce
Original PR description
### Steps to reproduce: - Enable developer mode - Go to Settings > Technical > Messages > ValueError: Cannot search, too many messages ### Cause of Issue: The new `ir.access` model introduced through…
### Steps to reproduce: - Enable developer mode - Go to Settings > Technical > Messages > ValueError: Cannot search, too many messages ### Cause of Issue: The new `ir.access` model introduced through https://github.com/odoo/odoo/pull/166359 inherits from `mail.thread` and enables tracking on the `active`, `domain`, and `operation` fields. https://github.com/odoo/odoo/blob/713f68333798575d70362cbb55ca31e91e75d5fa/addons/mail/models/ir_access.py#L7-L12 In production databases, every access rule modification generates a tracking message on the corresponding `ir.access` record. When a user opens Settings > Technical > Messages without any model filter, `_search_res_access` falls into the "enumerate all messages" path since no specific model is constrained in the domain. https://github.com/odoo/odoo/blob/713f68333798575d70362cbb55ca31e91e75d5fa/addons/mail/models/mail_message.py#L469-L473 This path calls `_filter_accessible_from_query`, which fetches messages up to `MAX_SEARCH_LIMIT` (= `PREFETCH_MAX * 10` = 10 000). https://github.com/odoo/odoo/blob/713f68333798575d70362cbb55ca31e91e75d5fa/addons/mail/models/mail_message.py#L614-L615 Because `ir.access` tracking messages alone can exceed that limit, the guard raises: > ValueError: Cannot search, too many messages ### Fix: Exclude messages whose `model` is `ir.access` from the enumeration domain when fetching generic messages to ensure important information is present without exceeding the messages limit. When the user's search domain already constrains the model to `ir.access` (e.g., when opening the chatter of a specific access rule record), `condition_values()` detects the model constraint and the per-model SQL path is taken instead — so those messages remain fully accessible in their own context. opw-6364325
The time taken by the AI to generate the placeholders during the configurator loading is sometimes exacly or slightly over 15 seconds, which results in a timeout. This commit increase the timeout time to 30 seconds. Also we lowered the translated ratio from 80% to 70% because some themes had a low translation ratio. task-6325919
Original PR description
The time taken by the AI to generate the placeholders during the configurator loading is sometimes exacly or slightly over 15 seconds, which results in a timeout. This commit increase the timeout time to 30 seconds. Also we lowered the translated ratio from 80% to 70% because some themes had a low translation ratio. task-6325919
**PROBLEM** When creating a Credit Note from a Sale Order, the credit note lines uses the default account instead of using the return account set on the company. **STEP TO REPRODUCE** 1. Create a SO with a product. 2. Create an invoice and confirm it. 3. Return to the SO, and reduce the product qty (product invoice policy should be ordered qty for these steps). 4. Click again on create Invoice to create a Credit Note for the SO. 5. Notice the account on the product line is not the retur
Original PR description
**PROBLEM** When creating a Credit Note from a Sale Order, the credit note lines uses the default account instead of using the return account set on the company. **STEP TO REPRODUCE** 1. Create a SO with a product. 2. Create an invoice and confirm it. 3. Return to the SO, and reduce the product qty (product invoice policy should be ordered qty for these steps). 4. Click again on create Invoice to create a Credit Note for the SO. 5. Notice the account on the product line is not the return account. **CAUSE** In `_create_invoices()` on the SO model, we first create the moves as invoice, and then switch them to credit note if the total is negative. This means the lines are created with the invoice default account. opw-6266882 Forward-Port-Of: odoo/odoo#274354
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages' in the settings - Create a tracked product with package - Put 10 units in stock in package `P`. - Create and confirm a sale for 5 units - Open the delivery, make sure the quantity is set to 0 - Click 'Details' - "Add a line" and select the package P -> if you try to select a destination p
Original PR description
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages'…
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages' in the settings - Create a tracked product with package - Put 10 units in stock in package `P`. - Create and confirm a sale for 5 units - Open the delivery, make sure the quantity is set to 0 - Click 'Details' - "Add a line" and select the package P -> if you try to select a destination package, the package P is not proposed as it should - save it and reopen 'Details' -> if you try to select a destination package, the package P is now proposed **Cause** The domain of `result_package_id` (destination package) correctly includes `package_id`: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L52-L56 However, before saving, `package_id` is not yet populated into the new `stock.move.line` record. It will only be copied from `quant_id` by `_copy_quant_info()`: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L1016-L1025 which will only be called in the create method, while saving: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L350 opw-6370159 Forward-Port-Of: odoo/odoo#277797
Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never fol
Original PR description
Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never follows the server counter again. This commit freezes that state only while something is still unread locally. This also fixes the flaky test "no unread message banner after message is deleted". https://runbot.odoo.com/odoo/error/242776 Forward-Port-Of: odoo/odoo#279601 Forward-Port-Of: odoo/odoo#279195
added tags for accounts and new demo data for l10n_cl_reports f29 refactor refactor file to company_demo.xml Add widthholding tax 2nd category for 2027 and 2028 since it is suitable for this report compatibility [FIX] l10n_cl: add more taxes and fix translation [FIX] l10n_cl: adapt fiscal position to new scheme. [FIX] l10n_cl: remove unused tags [FIX] l10n_cl: add fiscal position to taxes and replacement tax. Change refs in demo and fix demo values to make more consistent with real cases
Original PR description
added tags for accounts and new demo data for l10n_cl_reports f29 refactor refactor file to company_demo.xml Add widthholding tax 2nd category for 2027 and 2028 since it is suitable for this report compatibility [FIX] l10n_cl: add more taxes and fix translation [FIX] l10n_cl: adapt fiscal position to new scheme. [FIX] l10n_cl: remove unused tags [FIX] l10n_cl: add fiscal position to taxes and replacement tax. Change refs in demo and fix demo values to make more consistent with real cases [FIX] l10n_cl: change monthy taxes payable 210760 from payable to current [FIX] l10n_cl: add new ILA accounts to COA and fix ILA tax repartition lines Compatibility with 'remove tax_tag_invert' [FIX] l10n_cl: fix 'compras de combustibles' task-4329648 Forward-Port-Of: odoo/odoo#247545
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users & Companies > Companies and create two companies c1 and c2 3. Go to Website > Configuration > Websites and create two websites w1 with company c1 and w2 with company c2 4. Change the order of the websites so that w1 is at the top 5. Go to Website > eCommerce > Pricelists and create a pricelist pl
Original PR description
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users &…
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users & Companies > Companies and create two companies c1 and c2 3. Go to Website > Configuration > Websites and create two websites w1 with company c1 and w2 with company c2 4. Change the order of the websites so that w1 is at the top 5. Go to Website > eCommerce > Pricelists and create a pricelist pl1 in c1 assigned to w1 and pl2 in c2 assigned to w2 6. In an incognito tab, go to w1 and create a new account 7. As admin, go to Website > Configuration > Websites and change the order of the websites so that w2 is at the top 8. In an incognito tab, connect with the previously created account and go to the shop 9. An error is thrown (This error only happens when geoip works, i.e. when `_get_geoip_country_code` returns something) Issue: When geoip returns a country code, we search through all the pricelists available for that country code but some of them can be restricted to a company which raises an access error. We need to be able to access them in order to filter the ones that are not available on the current website Solution: Access all pricelists with sudo, they will be filtered out with `_is_available_on_website` opw-3574089 Forward-Port-Of: odoo/odoo#279697 Forward-Port-Of: odoo/odoo#268863
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used
Original PR description
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used while preserving the existing validation against empty or whitespace-only names. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279620 Forward-Port-Of: odoo/odoo#273593
In the `render_task_templates` branch, the `has_template_ancestor` step called `.toList({})`, turning `domain` into a plain list. It was only rebuilt into a `Domain` when a `default_project_id` was in context, so otherwise the trailing `domain.toList({})` threw `TypeError: domain.toList is not a function`. Introduced in 694ea6a2fb60 (odoo/odoo#279015). Fix: drop the premature `.toList({})` so `domain` stays a `Domain` until the single final conversion. Appeared on many clickAll failures assig
Original PR description
In the `render_task_templates` branch, the `has_template_ancestor` step called `.toList({})`, turning `domain` into a plain list. It was only rebuilt into a `Domain` when a `default_project_id` was in context, so otherwise the trailing `domain.toList({})` threw `TypeError: domain.toList is not a function`.
Introduced in 694ea6a2fb60 (odoo/odoo#279015).
Fix: drop the premature `.toList({})` so `domain` stays a `Domain` until the single final conversion.
Appeared on many clickAll failures assigned to the JS team:
https://runbot.odoo.com/odoo/error/944607Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037