Friday, April 3, 2026
24 changes · saas-19.2
New functionality added to Odoo
This update adds support for Peppol's Business Level Responses (BLR) for invoices and credit notes. These responses are required for Odoo to correctly interact with the Peppol network, ensuring accurate document exchange and compliance with European standards. This improves Odoo's integration with international trade and simplifies invoice processing.
Original PR description
Peppol offers a response system to the document received through it. These are called Business Level Responses, and their documentation can be found here:…
Peppol offers a response system to the document received through it. These are called Business Level Responses, and their documentation can be found here: https://docs.peppol.eu/poacc/upgrade-3/profiles/63-invoiceresponse/#introduction-to-openpeppol-and-bis The specific BLR implemented in this commit is targeted to invoices and credit notes. 3 types of responses are mandatory for a Peppol participant to correctly adhere to the BLR service: acknowledgement (different to the transport ack), confirmation and rejection. More response's types are available but were not implemented as they're not mandatory/needed (for now). For rejection, a list of at least one reason must be given, and actions can be suggested to the sender of the document for the eventual next invoice shipment. Same principle goes for Nemhandel, with some differences: only 2 responses, BusinessAccept and BusinessReject (no Acknowledgement, and no reasons are needed in case of rejection. Instead, the user can send a string message. iap PR: https://github.com/odoo/iap-apps/pull/1364 task-5237698 Forward-Port-Of: odoo/odoo#243191
Resolved issues and error corrections
This update resolves an issue where rejecting a PoS order could trigger duplicate kitchen ticket printing. The fix prevents this by ensuring the print token is properly managed during order rejection, ensuring tickets are printed correctly and avoiding unnecessary operations. This improves the reliability of order processing for our restaurant clients.
Original PR description
Bug fix: - Prevent duplicate kitchen ticket printing on order rejection. When a user rejects an order, the reject RPC triggers a webhook that calls _fetchPlatformOrder on all devices. This led to deleteOrders being called twice (once by the reject flow, once by the webhook). Fix: claim the print token via mark_platform_prep_order_as_printed in _rejectOrder before sending the reject RPC, so no device gets isReadyToPrint=true from the webhook. - Preparation needs to be sent after PoS accepts the order. ticket-6071740 Forward-Port-Of: odoo/enterprise#112277
This update resolves an issue where users couldn't successfully undo rescheduling calendar events. The fix removes a problematic data field ('originId') before the system writes event data to the database, preventing a data error. This ensures the undo functionality works as expected.
Original PR description
Currently, an error occurs when user tries to undo a calendar event. Steps to replicate: - Install `appointment` with demo data. - Navigate to `Appointments > Schedule > Resource Booking`. - Drag to…
Currently, an error occurs when user tries to undo a calendar event. Steps to replicate: - Install `appointment` with demo data. - Navigate to `Appointments > Schedule > Resource Booking`. - Drag to create a calendar event. - Reschedule the event to a later time (drag and drop forward). - Click Undo on the notification that appears. Error: `ValueError: Invalid field 'originId' in 'calendar.event'` `KeyError: 'originId'` Cause: - The key `originId` was patched in the `getschedule()` [1] and later when user tried to undo the calendar event, the [fallbackschedule] included the key `originId` and made an [orm] call with it. - The [line] tries to write the data into the database where `originId` field doesnt exist and causes the error to occur. Solution: - Remove the `originId` key from `fallbackdata` before the orm call. [1]: https://github.com/odoo/enterprise/blob/e61eef059983bb0cdec4f156fb9283198b379863/appointment/static/src/views/gantt/gantt_renderer.js#L110-L116 [fallbackschedule]: https://github.com/odoo/enterprise/blob/e61eef059983bb0cdec4f156fb9283198b379863/web_gantt/static/src/gantt_renderer.js#L1425 [orm]: https://github.com/odoo/enterprise/blob/e61eef059983bb0cdec4f156fb9283198b379863/web_gantt/static/src/gantt_renderer.js#L1473-L1477 [line]: https://github.com/odoo/enterprise/blob/e61eef059983bb0cdec4f156fb9283198b379863/web_gantt/models/models.py#L248 sentry-7020359653 Forward-Port-Of: odoo/enterprise#112766 Forward-Port-Of: odoo/enterprise#100570
This update addresses a previous memory issue that occurred when calculating depreciation for large customer records. The fix uses a more efficient method to process data, preventing the system from running out of memory and ensuring accurate depreciation calculations for all records. This resolves a problem previously impacting the 16.0 version.
Original PR description
The previous compute method loaded all moves records into memory, which caused an out-of-memory issue for large number of record. Replaced the logic with read_group aggregation to perform the…
The previous compute method loaded all moves records into memory, which caused an out-of-memory issue for large number of record. Replaced the logic with read_group aggregation to perform the calculation using sql and reduce memory usage.
Note: the issue is faced during 16.0 version too but as 16.0 is no more supported for bug fix. So, doing it from 17.0 version.
```
Traceback (most recent call last):
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 333, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 346, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 506, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 657, in mock_view_tree
self.mock_web_search_read(model, view, [domain], fields_list)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 691, in mock_web_search_read
data = model.search_read(domain=domain, fields=fields_list, limit=80, order=filter_order(model))
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5074, in search_read
result = records.read(fields, **read_kwargs)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3038, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3219, in _read_format
vals[name] = convert(record[name], record, use_name_get)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 6007, in __getitem__
return self._fields[key].__get__(self, self.env.registry[self._name])
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1222, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1404, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/16.0/addons/mail/models/mail_thread.py", line 403, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 4276, in _compute_field_value
fields.determine(field.compute, self)
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 98, in determine
return needle(*args)
File "/home/odoo/src/enterprise/16.0/account_asset/models/account_asset.py", line 293, in _compute_value_residual
posted_depreciation_moves = record.depreciation_move_ids.filtered(lambda mv: mv.state == 'posted')
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5496, in filtered
return self.browse([rec.id for rec in self if func(rec)])
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5496, in <listcomp>
return self.browse([rec.id for rec in self if func(rec)])
File "/home/odoo/src/enterprise/16.0/account_asset/models/account_asset.py", line 293, in <lambda>
posted_depreciation_moves = record.depreciation_move_ids.filtered(lambda mv: mv.state == 'posted')
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1187, in __get__
recs._fetch_field(self)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3245, in _fetch_field
self._read(fnames)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3351, in _read
self.env.cache.insert_missing(fetched, field, values)
File "/home/odoo/src/odoo/16.0/odoo/api.py", line 1123, in insert_missing
field_cache.setdefault(id_, val)
MemoryError
```
opw-5921410
upg-3891767
Forward-Port-Of: odoo/enterprise#109008This update fixes an issue where flexible work schedules were incorrectly displaying an inflated number of expected hours (48 instead of 40). The fix addresses a time zone calculation error, ensuring that attendance hours are accurately reflected based on an employee's actual working time, regardless of their location.
Original PR description
__ ## Short functional explanation of the error When the time zone of an employee's schedule is different from the employee's time zone, and that the employee's time zone has more than 9 hours of…
__ ## Short functional explanation of the error When the time zone of an employee's schedule is different from the employee's time zone, and that the employee's time zone has more than 9 hours of difference with UTC. The schedule is flexible and is set to 40 hours per week. When we open the Attendances app, the expected hours for this employee show 48. ## Reproduction Steps 1. Create an employee. The time zone of the employee should be different from the one on his work schedule. To be sure to replicate the bug, set the time zone of employee's time zone to Pyongyang. 2. Open the work schedule and set it to Flexible. Set the weekly hours to 40, and the full time equivalent to 40. Set the work schedule to Europe/Brussels time. 3. Open Attendances. ### Expected behavior When we hover the name of our employee, we can see in white on green background 0/40h. ### Unexpected behavior Instead, we see 0/48h. ## Origin of the issue This line: https://github.com/odoo/odoo/blob/e49536031f61b90212eb6f0d1a8a3e15927e723d/addons/resource/models/resource_calendar.py#L419 is used to retrieve the correct date. We assume that `end_datetime` will be set at midnight, so subtracting one second gives us the day before, allowing us to ignore the date of `end_dt`, for which we don't need to compute the intervals. However, this doesn't take into account different time zones. Indeed, we compute `end_datetime_adjusted` from `end_datetime`, which has the user timezone, and not UTC, as defined here: https://github.com/odoo/odoo/blob/e49536031f61b90212eb6f0d1a8a3e15927e723d/addons/resource/models/resource_calendar.py#L402 As a result, if we set the user timezone to Pyongyang, `end_datetime` will be set at 8am, and `end_datetime_adjusted` will lead to the same date, instead of a day before. Hence, we would compute an additional interval for an additional day, which would in the end give us 48 hours expected instead of the 40 hours indicated in the contract. Therefore, we have to take into account the time zones, hours, minutes and seconds when checking the start and end dates. __ opw-5937298 Forward-Port-Of: odoo/enterprise#110011
This update resolves an issue where product exports from the Web Studio were not functioning correctly due to a change in how product creation logic was implemented. The fix adds a necessary context key, ensuring that product templates are properly created and exported, improving the reliability of this key business process.
Original PR description
This commit https://github.com/odoo/odoo/pull/254323 changed the way product( template)s are created, which now decouples the logic into two context attributes instead of one. This commit fixes this by adding the second one. Forward-Port-Of: odoo/enterprise#112753
This update resolves an issue where the LPP (Labor Pension Payment) was incorrectly applied to employee salaries in the Swiss payroll module, specifically when employees were not covered by insurance. The fix ensures accurate LPP calculations based on proper insurance status, improving payroll accuracy and compliance.
Original PR description
Forward-Port-Of: odoo/enterprise#112824
This update fixes an access error within the Frontdesk module that prevented users with limited employee permissions from creating new stations or visitors. The fix involved updating the Frontdesk module to adhere to a new Odoo standard regarding many2many fields linked to HR employees, ensuring proper access controls.
Original PR description
Issue: ---------------------------------------- When a user with administrator rights on frontdesk but no rights on employees try to create a new station or visitor, they get an access error. Steps to reproduce: ---------------------------------------- - Have a user with administrator rights on Frontdesk but no rights on Employees - Switch to this user - Open Frontdesk and try to create a new station - Access Error Cause: ---------------------------------------- Since [this commit](https://github.com/odoo/odoo/commit/71f662b827b58c4f8ed1260728dc5194201ec323) models having a many2many field on `hr.employee` must inherit from `hr.mixin` to avoid an access error. The Frontdesk module was not changed. Solution: ---------------------------------------- Make `frontdesk.visitor` and `frontdesk.frontdesk` inherit `hr.mixin` opw-6000417 Forward-Port-Of: odoo/enterprise#112893 Forward-Port-Of: odoo/enterprise#110084
This update corrects a visual glitch on mobile devices where the dynamic product snippet would jump unexpectedly when scrolling. The fix removes a setting that caused the snippet to repeatedly re-render, leading to inconsistent display behavior. This ensures a smoother and more reliable user experience across different screen sizes.
Original PR description
Scenario: - add the dynamic Products snippet on top of page and save - go to the website with browser address bar that change height when going when going down in the page (hide or change size of it…
Scenario: - add the dynamic Products snippet on top of page and save - go to the website with browser address bar that change height when going when going down in the page (hide or change size of it that is changing the viewport size) - scroll all the way up and down in the page Result: there is some jump that happen when the browser interface change size when scrolling down or up. Cause: When going down the page, the viewport size changes (because the address bar gets bigger / smaller). This causes the dynamic snippet to be re-rendered. Since February 2026 commit 2e5bd409581ddaab28084c42ab51b50b494f4876 to optimize performance, product blocks are only rendered when the are in the viewport (may depends on browser) with "content-visibility: auto". The combination of those two things, causes that if you scroll down, the widget is re-rendeded in owl, but it is only rendered in the page once you scroll in the viewport so the scroll jump up or down with the products snippet being rendered (going from 0 to eg. 300px when scrolling into viewport) or not being rendered (going from eg 300px to 0 when scrolling and the widget not being in viewport). Fix: remove the "content-visibility: auto" when we are in the dynamic "Products" snippet, it was intended for the shop view and not for the case where product block can be re-rendered outside of viewport. opw-6005340 Note: this is mainly happening on mobile browser (eg. safari on iOS) because of the viewport resize when scrolling, but this can somehow be reproduced on chrome desktop: - scroll below a "Products" snippet, change browser window size manually => the should be a jump of the content up - scroll up to go back to the product snippet => the content of product snippet should appear all at once when the 0 pixel heigh get in the viewport Forward-Port-Of: odoo/odoo#256815
This update resolves an error that occurred when rearranging sections within sale order lines. The fix ensures that the system correctly handles changes to order lines, preventing errors during editing and improving the user experience when managing sales quotes. This improves the reliability of the sales order management process.
Original PR description
Moving a section around in sale order lines when there is a line that can be abandoned throws an error Steps to reproduce: 1. Install Sales app 2. Go to Sales and create a new quotation 3. Add any…
Moving a section around in sale order lines when there is a line that can be abandoned throws an error Steps to reproduce: 1. Install Sales app 2. Go to Sales and create a new quotation 3. Add any product, then add a section: enter any name for the section and then immediately press Enter (it should create an empty product line) 4. Without leaving edit mode, drag and drop the section at the top of the sale order lines (the empty product line should still be there) 5. An error is thrown The same issue can be reproduced by moving a section down: 3b. Add any product, then add a section: move it to the top of the order lines then enter any name for the section and immediately press Enter (it should create an empty product line) 4b. Without leaving edit mode, drag and drop the section just between the product line and the empty product line Issue: `sortDrop` calls `leaveEditMode` at https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/web/static/src/views/list/list_renderer.js#L2242 which removes order lines that can be abandoned https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/web/static/src/model/relational_model/static_list.js#L379-L381 This can remove records from the recordMap generated before calling `super.sortDrop` in https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/sale_management/static/src/fields/sale_order_line_field/sale_order_line_field.js#L175-L182 so we end up calling `_handleQuantityAdjustment` with a recordMap that contains record ids that have been deleted, throwing an error when we try to access the deleted record Solution: Call `leaveEditMode` before computing recordMap in order to remove the records that can be abandoned. This prevents `this.props.list.records` from being different when we generate recordMap and when we call `_handleQuantityAdjustment`. We also need to set the record being moved as dirty. This prevents the record from being abandoned when `leaveEditMode` is called. opw-6022538 Forward-Port-Of: odoo/odoo#256662
This update fixes a bug where dropdowns wouldn't close correctly when clicking outside the initial active UI element. The change expands the area where clicks trigger closing, ensuring consistent behavior with popovers and other UI elements, resolving a VoIP issue.
Original PR description
[FIX] web: fix dropdown closing logic when clicking outside active UI Before this commit, the dropdown were closed when clicking outside... but only if the element that was clicked belongs to the…
[FIX] web: fix dropdown closing logic when clicking outside active UI
Before this commit, the dropdown were closed when clicking outside...
but only if the element that was clicked belongs to the same "UI
active element" as the one that was the current one when the dropdown
was opened.
That is not perfect:
- Open some popover that becomes the "UI active element"
- Open the user menu dropdown (which is thus outside the current "UI
active element")
- Click just below that user menu dropdown
=> It does not close.
It will only close when clicking in the registered "UI active element",
which is not logical.
This commit improves the logic: the close also occurs if the click
occurs in *an ancestor* of the old registered "UI active element". That
still keep the idea of checking "UI active elements" at all, for example
in the case "dropdown -> dialog -> dropdown -> click outside", which
should not close the first dropdown, as in that case it is the opposite
situation: the click occurs in a *child* "UI active element" of the old
registered one.
This fix is needed to fix a VoIP issue, where the "popover" mentioned
in the example above is the VoIP softphone. See enterprise counter-part
for more precisions.
[FIX] web: fix dropdown closing logic after closing active UI elements
The parent commit fixes the dropdown closing logic when clicking outside
"UI active elements". But it was not enough:
- Open some popover that becomes the "UI active element"
- Open the user menu dropdown (which is thus outside the current "UI
active element")
- Close the popover with some keyboard shortcut
- Click just below that user menu dropdown
=> It still does not close, although we are in a situation without any
"UI active element".
This commit improves the logic again: the close also occurs if the click
occurs while the old registered "UI active element" is gone.
This fix is needed to fix a VoIP issue, where the "popover" mentioned
in the example above is the VoIP softphone. See enterprise counter-part
for more precisions.
task-6055692This update fixes an issue where the departure date for Belgian employees wasn't editable after termination. The change allows HR staff to manually set the departure date when an employee is on 'partial working' notice, ensuring accurate payroll calculations and improved employee management. This resolves a conflict between automated and manual date adjustments.
Original PR description
Steps to reproduce: - Create an employee with a valid contract in a belgian company - End their colloboration with the reason 'Fired' - Set their notice_respect to 'partial working' - Edit the departure date to any date other than the pre-computed one and save your changes - The date will be automatically reverted to the precomputed one Cause: The cyclic dependency between the departure_date and the actual_notice_period fields where causing a conflict while trying to set the desired dates. Solution: Added a dummy inverse function that just permits manual changing of the departure date without triggering the computation function Task: 6036368 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an error that occurred when users paid for orders through the website using gift cards. The fix ensures that email notifications are properly processed without attempting to access deleted email records, preventing the error. This improves the reliability of the gift card ordering process.
Original PR description
Currently, an error occurs when a user pays for their order through the website. **Steps to Reproduce:** - Install the `website_sale` and `pos_loyalty` modules. - Create a `product`. - Go to `Gift…
Currently, an error occurs when a user pays for their order through the website. **Steps to Reproduce:** - Install the `website_sale` and `pos_loyalty` modules. - Create a `product`. - Go to `Gift Cards & eWallets` and create a program with the type set to `Gift Card`. - Generate at least `one gift card`. - In `Gift Card Products`, add the recently created `product`. - Ensure that the SMTP server is configured and the `Demo` payment provider is `enabled`. - Make sure that in the `Gift Card: Gift Card Information` email template, the `Send From` field is set. - Now, go to the `shop`, add the product to the cart, and proceed to `Checkout` > `Pay`. - And the error appears in the `logs`. **Error:** `odoo.exceptions.MissingError: Record does not exist or has been deleted.` `(Record: mail.mail(5,), User: 1)` After this [recent commit], when user pays for their order, the Payment: Post-process transactions step confirms the order and attempts to send reward coupon email [1] if any coupon is applied to the product. The system sends the email with force_send=True [2] and retrieves the sent mail_ids [3]. because force_send=True, the email is sent immediately [4] instead of being queued. Once the email is successfully sent [5], _postprocess_sent_message [6] is triggered. Since there is no failure in sending the email, the corresponding mail record is deleted [7], because the email template has auto_delete=True. Later, when the system tries to access the deleted mail.mail record using the previously returned mail_ids, it raises error [8]. This commit ensures that only existing mail records are used when processing mail_ids, preventing access to deleted records. [recent commit]: https://github.com/odoo/odoo/commit/80d80a007131827ddd231bed320708068d0086b6 [1]: https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/sale_loyalty/models/sale_order.py#L188 [2]- https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/sale_loyalty/models/sale_order.py#L245 [3]: https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/pos_loyalty/models/loyalty_card.py#L73 [4]- https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/mail/models/mail_template.py#L815-L816 [5]: https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/mail/models/mail_mail.py#L871-L872 [6]: https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/mail/models/mail_mail.py#L919 [7]- https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/mail/models/mail_mail.py#L288-L289 [8]: https://github.com/odoo/odoo/blob/0f395269e9815977263f27fa85855096166e15a2/addons/pos_loyalty/models/loyalty_card.py#L73-L76 sentry-7367887795 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a bug where flexible work schedules with different time zones were incorrectly displaying an inflated number of expected hours (48 instead of 40). The change ensures accurate hour calculations by properly accounting for time zone differences, preventing overestimation of work time.
Original PR description
__ ## Short functional explanation of the error When the time zone of an employee's schedule is different from the employee's time zone, and that the employee's time zone has more than 9 hours of…
__ ## Short functional explanation of the error When the time zone of an employee's schedule is different from the employee's time zone, and that the employee's time zone has more than 9 hours of difference with UTC. The schedule is flexible and is set to 40 hours per week. When we open the Attendances app, the expected hours for this employee show 48. ## Reproduction Steps 1. Create an employee. The time zone of the employee should be different from the one on his work schedule. To be sure to replicate the bug, set the time zone of employee's time zone to Pyongyang. 2. Open the work schedule and set it to Flexible. Set the weekly hours to 40, and the full time equivalent to 40. Set the work schedule to Europe/Brussels time. 3. Open Attendances. ### Expected behavior When we hover the name of our employee, we can see in white on green background 0/40h. ### Unexpected behavior Instead, we see 0/48h. ## Origin of the issue This line: https://github.com/odoo/odoo/blob/e49536031f61b90212eb6f0d1a8a3e15927e723d/addons/resource/models/resource_calendar.py#L419 is used to retrieve the correct date. We assume that `end_datetime` will be set at midnight, so subtracting one second gives us the day before, allowing us to ignore the date of `end_dt`, for which we don't need to compute the intervals. However, this doesn't take into account different time zones. Indeed, we compute `end_datetime_adjusted` from `end_datetime`, which has the user timezone, and not UTC, as defined here: https://github.com/odoo/odoo/blob/e49536031f61b90212eb6f0d1a8a3e15927e723d/addons/resource/models/resource_calendar.py#L402 As a result, if we set the user timezone to Pyongyang, `end_datetime` will be set at 8am, and `end_datetime_adjusted` will lead to the same date, instead of a day before. Hence, we would compute an additional interval for an additional day, which would in the end give us 48 hours expected instead of the 40 hours indicated in the contract. Therefore, we have to take into account the time zones, hours, minutes and seconds when checking the start and end dates. __ opw-5937298 Forward-Port-Of: odoo/odoo#252847
This update fixes an issue where timesheets were incorrectly calculating hours for employees on past contracts. The change ensures that leave periods under a historical contract accurately reflect the standard working hours from that period, resolving a discrepancy between the current and past contract schedules.
Original PR description
Currently on creating a time off that falls under a past contract still generates timesheet hours based on the employee's current contract. ### **Steps to Reproduce:** 1) Install…
Currently on creating a time off that falls under a past contract still generates timesheet hours based on the employee's current contract. ### **Steps to Reproduce:** 1) Install `project_timesheet_holidays` module with demo data. 2) Create an employee with two contracts/versions: - Past contract: 1 Jan 2025 to 31 Dec 2025 with standard 40h/week (8h/day). - Current contract: 1 Jan 2026 to indefinite with standard 35h/week (7h/day). 3) Create and validate Time off for this employee in the past (e.g, 29 Dec 2025) 4) Navigate to `Timesheets>All Timesheets`, search for this employee and switch list view for clear view. ### **Observed Behavior:** 7:00 hours are displayed on the timesheet, pulling from the employee's current active contract calendar. ### **Expected Behavior:** 8:00 hours should be displayed, as the leave date falls under the 40h/week past contract. ### **Root Cause:** In the `_generate_timesheets`, the caledar values is fetched using `employee_id.resource_calendar_id` see[1], which always points to the employee's currently active calendar. Furthermore, this calendar is not explicitly passed to `_list_work_time_per_day` see[1], causing the method to fall back on the current default. [1]- https://github.com/odoo/odoo/blob/c2595e47e3b36120f4c3da8bfe8c16f6c5969a70/addons/project_timesheet_holidays/models/hr_leave.py#L36-L55 ### **Fix:** Resolve the applicable contract version based on the leave period instead of relying on `employee.resource_calendar_id`, which always points to the current calendar after the `resource_calendar` [refactor](https://github.com/odoo/odoo/commit/47f20c293787710e9501b7fd378239813875864a). This fix fetches the version overlapping the leave dates and use its `resource_calendar_id` to compute work hours. Pass this calendar explicitly to `_list_work_time_per_day` to avoid fallback to the current employee calendar. This ensures that leaves created in past contract periods generate timesheets using the correct historical working schedule. **opw-5922695** Forward-Port-Of: odoo/odoo#254296 Forward-Port-Of: odoo/odoo#248207
This update resolves an issue preventing internal employees from accessing their overtime data within the employee dashboard. The fix adds a necessary security permission, ensuring all users can see their own overtime hours as intended. This improves usability and data visibility for all employees.
Original PR description
Steps to reproduce: 1. Enable "Display Extra Hours" in Attendance settings. 2. Assign an overtime ruleset to an employee. 3. Ensure the employee does not have the "Officer: Manage attendances" group.…
Steps to reproduce: 1. Enable "Display Extra Hours" in Attendance settings. 2. Assign an overtime ruleset to an employee. 3. Ensure the employee does not have the "Officer: Manage attendances" group. 4. Create an attendance that generates extra hours for this employee. 5. Log in as the employee and open the Employees app to view Extra Hours. Issue: An Access Error is raised because `get_overtime_data_by_employee` in `hr_holidays_attendance/models/hr_employee.py` performs a `_read_group` on `hr.attendance.overtime.line`. In 19.0, the only ACL for this model grants access to `group_hr_attendance_officer`: https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/hr_attendance/security/ir.model.access.csv#L1-L11 Users with `group_hr_attendance_own_reader` (implied by `base.group_user`, i.e. all internal users) have no read access to `hr.attendance.overtime.line`. In later versions, this was already fixed by adding a read-only ACL for `group_hr_attendance_own_reader` on this model: https://github.com/odoo/odoo/blob/ad4a2ec11fea2058445e4003099af3a5caa1ef22/addons/hr_attendance/security/ir.model.access.csv#L13 This is why forward-ports are not needed. Solution: Add the missing `access_hr_attendance_overtime_line_own_reader` ACL to grant read-only access to `group_hr_attendance_own_reader` on `hr.attendance.overtime.line`, matching the approach used in later versions. This is preferred over using `.sudo()` as it properly grants the intended access right rather than bypassing security checks entirely. opw-6055081 Forward-Port-Of: odoo/odoo#257301 Forward-Port-Of: odoo/odoo#255576
This update resolves an issue where Ctrl+A followed by Delete wouldn't remove all content from editable areas when the first element was non-editable. The fix ensures the selection correctly anchors and removes the entire editable content, improving the editor's functionality and user experience.
Original PR description
Description of the issue this PR addresses: - When an element with `contenteditable="false"` is the first node in the editable, pressing Ctrl+A followed by Delete does not remove the entire selection and instead deletes only the last character. Desired behavior after PR is merged: - Ensure that the selection is anchored to the deepest editable position when performing a select-all operation so that the full editable content is correctly selected and removed. Steps to reproduce: - Insert a toggle list using `/togglelist` in a new todo - Add one or more paragraphs below it and enter some text - Select all content using Ctrl+A - Press Backspace to delete the selection - Observe that only the last character is removed Backport of: 67e6a617def3bf4f9eb6b63b0850f5cfc773bccc task-5363926 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#257070 Forward-Port-Of: odoo/odoo#241696
This update resolves a crash that occurred when deleting HTML fields used in website forms. The issue stemmed from the way these fields were initially parsed as XML, leading to an error. This fix ensures that field deletions are handled correctly, preventing website disruptions.
Original PR description
Steps to reproduce ================== tl;dr: html fields are parsed as xml - Go to Helpdesk > Tickets > Warranty - Open studio - Add a new text field named "TEST" - Remove it from the view - Exit studio - Go to the website - Click on new - Add a new blogpost - Set a title and save - Click on "Contact & Forms" - Click on the first block - Click on the form - Change the form action to "Create a ticket" - Click on "+ Field" - Change the Type selection to "TEST" - Click on save - Enable debug mode - Go to "Settings / Technical / Database Structure / Fields" - Type x_ in the search bar and press enter - Delete the field => lxml.etree.XMLSyntaxError Cause of the issue ================== When deleting a field, `_check_if_used_in_website_form` is called to prevent the deletion if a field is used in an html field. The html fields were parsed with an xml parser.. opw-5946029 Forward-Port-Of: odoo/odoo#257245 Forward-Port-Of: odoo/odoo#256066
This update resolves an issue where submitting the 'Create a Task' form would fail if an invalid email address was entered. The fix removes a problematic field that was incorrectly adding invalid email addresses to task records, preventing the form from submitting successfully. This ensures users can consistently create tasks with valid email information.
Original PR description
Currently, an error occurs when a user submits the Create a Task form. **Steps to Reproduce:** - Install the `website_project` module. - Go to `website` > `Click on Edit` > `Drag and drop` form. -…
Currently, an error occurs when a user submits the Create a Task form. **Steps to Reproduce:** - Install the `website_project` module. - Go to `website` > `Click on Edit` > `Drag and drop` form. - Click on the form and, set the action to `Create a Task`, then save. - Fill in the required data in the form. - In the `Email Address` field, enter an email that does not correspond to any existing partner. - `Submit` the form, and the `error appears in the logs`. `ValueError: Invalid field 'email_cc' in 'project.task'` With this [recent commit], the email_cc field has been removed from project.task, along with the mail.thread.cc inheritance, because threads are now able to find CC recipients. so, when user submits the form with an email address that does not correspond to any existing partner, the system adds email_cc to the record [1], and when it attempts to create the record [2], it raises an error. This commit ensures that email_cc is no longer added to the record. [recent commit]: https://github.com/odoo/odoo/commit/3c26c0553754a75d9440097ad473be3cc8bcb320#diff-93ba226020add6481cfeab916e69980a59163e2925a5c2c9a3bc0aaceb484cdf [1]- https://github.com/odoo/odoo/blob/21aa7e7eca0bf78978e0667cee43129985833166/addons/website_project/controllers/main.py#L61 [2]: https://github.com/odoo/odoo/blob/21aa7e7eca0bf78978e0667cee43129985833166/addons/project/models/project_task.py#L1167 sentry-7374084515 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update optimizes the HTML editor's performance by making several key changes to how it processes HTML content. Specifically, it reduces unnecessary calculations and delays certain checks, resulting in faster rendering times. This improves the overall responsiveness and efficiency of the Odoo application.
Original PR description
Description of the issue/feature this PR addresses: This PR improves the performance of several `normalize_handlers` by reducing expensive DOM/style checks, avoiding unnecessary layout recalculations. This PR: 1. Replaces the usage of `fillEmpty` with manual filling of empty blocks. 2. Replaces `isBlock` with `!isPhrasingContent`, which better matches the actual use case and avoids unnecessary work. 3. Optimizes list normalization by reducing checks for `isBlock`. 4. Avoids style recalculations in `normalizeInline` of `qweb_plugin`. 5. Delays the `isBlock` check at certain places so it is only performed when needed. 6. Reduces the number of `isBlock` calls in `selection_placeholder_container_predicates` and `selection_blocker_predicates`. 7. Fixes layout thrashing by separating style reads from style writes. task-5245157 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255310
This update resolves an issue where deleting a public holiday incorrectly created timesheets for all related leave requests, even canceled ones. Now, deleting or modifying a holiday will only generate timesheets for valid, approved leaves, streamlining the timesheet process and preventing unnecessary entries. This ensures accurate timesheet reporting.
Original PR description
…d leaves Description of the issue/feature this PR addresses: When a public holiday is edited or deleted, the timesheet re-creation is erroneously done for *all* leaves, even those which are canceled or still in draft. Steps to Reproduce: 1. Create a Time Off request for a timesheet-creating leave type (i.e. `timesheet_generate = True`) that overlaps with a public holiday. 2. Refuse the Time Off request. 3. Delete the public holiday the request overlaps with. Current behavior before PR: The deletion of the holiday causes timesheet entries to be created, even though it's a refused request. Desired behavior after PR is merged: The deletion or editing of the public holiday only re-creates the timesheets for the leaves that are actually valid and thus need timesheet entries. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255155 Forward-Port-Of: odoo/odoo#250372
This update resolves an issue preventing website users from seeing product ratings on certain items. Previously, access to rating data was restricted, causing an error for public visitors. This change ensures all users can view and interact with product ratings on the website.
Original PR description
**Steps to produce:** - Install the `Ecommerce` module. - Create a product. - In the Sales tab, set an alternative product and ensure both are published. - Open the product page on the website and enable `reviews` from the editor. - Open the same product page in incognito mode. **Issue:** ``` AccessError: You do not have enough rights to access the field "rating_avg" on Product Variant (product.product). ``` Root cause: --- - Currently, product records in dynamic snippets to be fetched without superuser privileges. Since the `rating_avg` field is restricted to internal users, public visitors encounter an `AccessError` when viewing snippets with ratings enabled. - Similar approach used [here]. [here]: https://github.com/odoo/odoo/commit/12bb994da4c3222e8c7fb2df95c202a6c45a28b0 opw-6065319 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#257400 Forward-Port-Of: odoo/odoo#256570
This update fixes a potential issue where invoices with both price-included and zero-price excluded taxes were incorrectly calculating tax totals. The change ensures that tax calculations are accurate, regardless of whether a price excluded tax line is present, improving invoice accuracy and financial reporting. This resolves a previous bug reported in opw-6060486.
Original PR description
…xes_data Suppose an invoice with price-included taxes but with a zero price excluded one. We don't want to fallback on the excluded mode just for that. opw-6060486 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#257495
This update fixes an issue where new projects created from CRM leads were incorrectly defaulting to the project template's company instead of the lead's company. This resulted in data inconsistencies and a user error. The change ensures that the project inherits the correct company information, improving data accuracy and the user experience.
Original PR description
When creating a project from a CRM lead using a template, the `default_company_id` set by `_get_project_create_from_lead_context` is ignored because `company_id` is not in the template default…
When creating a project from a CRM lead using a template, the `default_company_id` set by `_get_project_create_from_lead_context` is ignored because `company_id` is not in the template default context whitelist. This causes the new project to inherit the template's company instead of the lead's company, resulting in a company mismatch with the partner and a UserError. https://github.com/odoo/odoo/blob/2b89db4af2265e5cec8feb11853364e293de203e/addons/crm_sale_project/models/crm_lead.py#L37-L45 https://github.com/odoo/odoo/blob/2b89db4af2265e5cec8feb11853364e293de203e/addons/project/models/project_project.py#L1413-L1419 Steps To Reproduce: 1. Go to CRM, create or open a lead. 2. Clear the contact field and save. 3. Click the gear icon → Create Project. 4. Select any project template (not empty) and submit. Ticket [link](https://www.odoo.com/odoo/project.task/5933253) opw-5933253 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#250087