Tuesday, August 11, 2026
37 changes · saas-19.4
Enhancements to existing features
The checks the Tax Agency performs are always based on the latest version of their XSD (no API versioning), but the XSD URI changes with each new version of the checks. Since it's not functionally used, it's not so important to keep it always updated and yet now: - we now update the export templates to have the latest `schemalocation` URI for once. - we start ignoring namespaces in l10n_it_* XML tests - we start ignoring the root FatturaElettronica tag's namespace attributes so there
Original PR description
The checks the Tax Agency performs are always based on the latest version of their XSD (no API versioning), but the XSD URI changes with each new version of the checks. Since it's not functionally used, it's not so important to keep it always updated and yet now: - we now update the export templates to have the latest `schemalocation` URI for once. - we start ignoring namespaces in l10n_it_* XML tests - we start ignoring the root FatturaElettronica tag's namespace attributes so there won't be a problem in case we change the `schemalocation` again. Forward-Port-Of: odoo/odoo#281509 Forward-Port-Of: odoo/odoo#275345
Don't generate a task every time the payroll officer assigns a new driver to the car. task-6425360 Forward-Port-Of: odoo/odoo#279103
Original PR description
Don't generate a task every time the payroll officer assigns a new driver to the car. task-6425360 Forward-Port-Of: odoo/odoo#279103
This PR improves the Call Debrief experience across screen sizes and adapts the UI by: - Use a two-column layout on larger screens when both video and transcription are available. - Make the layout adapt correctly in full-screen mode. - Refines the style of silent sections. - Enable full-screen mode on all devices above the mobile breakpoint by using `env.isSmall` instead of `isMobileOS`. task-6328684 Requires: - https://github.com/odoo/enterprise/pull/122029 --- I confirm
Original PR description
This PR improves the Call Debrief experience across screen sizes and adapts the UI by: - Use a two-column layout on larger screens when both video and transcription are available. - Make the layout adapt correctly in full-screen mode. - Refines the style of silent sections. - Enable full-screen mode on all devices above the mobile breakpoint by using `env.isSmall` instead of `isMobileOS`. task-6328684 Requires: - https://github.com/odoo/enterprise/pull/122029 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This avoids a useless blocking rpc call when opening the systray. Task-6131386 Forward-Port-Of: odoo/odoo#276709 Forward-Port-Of: odoo/odoo#269797
Original PR description
This avoids a useless blocking rpc call when opening the systray. Task-6131386 Forward-Port-Of: odoo/odoo#276709 Forward-Port-Of: odoo/odoo#269797
Resolved issues and error corrections
The payroll off-cycle action now works when users select several payslips at once from the list view. This prevents an error screen and lets payroll teams process multiple payslips more smoothly.
Original PR description
Steps to reproduce: - Open payslip list view - Select multiple payslips - Select "Send to Off-cycle" action Issue: A traceback occurs with ValueError: Expected singleton when the action is executed on multiple payslips. Reason: - 'action_move_to_off_cycle()' assumes a singleton and directly accesses self.version_id.id - When multiple payslips are selected from list view then self contains several payslips and self.version_id returns multiple versions, causing the singleton error. Solution: - Iterate over each payslip individually when processing the off-cycle action and use the corresponding version for each record, allowing the action to work correctly in multi-record mode task-6320059
Code cleanup and technical improvements
We now use `sys.excepthook` and `threading.excepthook` to catch any unhandled exception in the logfile. This improvement allows logging exceptions as a whole instead of line by line. This will simplify debugging with Sentry.
Original PR description
We now use `sys.excepthook` and `threading.excepthook` to catch any unhandled exception in the logfile. This improvement allows logging exceptions as a whole instead of line by line. This will simplify debugging with Sentry.
Bank statement matching now uses an existing optimized database index when looking for unreconciled accounting entries. This should improve performance for related accounting workflows without changing user-facing behavior.
Original PR description
We have a very efficient index for searching unreconciled lines on known accounts. Let's use it.
```python
_unreconciled_index = models.Index("(account_id, partner_id) WHERE reconciled IS NOT TRUE")
```
Before this change, the query planner didn't recognize the index because of its definition being slightly different wrt the null values.
Forward-Port-Of: odoo/enterprise#127093A restaurant appointment test now properly closes an edited form before finishing. This prevents random test failures and helps keep future updates to the restaurant appointment feature stable.
Original PR description
The `test_appointment_kanban_view` tour test was randomly failing with the following error: `AssertionError: Tour finished with a dirty form view being open.` This occurred because the tour ended right after clearing a date field on a form, leaving the form in a "dirty" (unsaved changes) state. This commit fixes the issue by adding a final step to the tour that clicks the cancel/discard button. Forward-Port-Of: odoo/enterprise#109633
Fixed an issue where opening Bank Matching from a return could fail when no bank journal was selected. This prevents an error screen and lets users continue reconciliation from the working file flow.
Original PR description
When accessing the reconciliation widget from the working file check, there is no journal to be selected, hence no journal in the context. This was tracebacking since we were trying to send a read query to the server with an undefined id. To reproduce: * create a bank statement line without reconciling * set up the return on the misc journal * open the return, then "Bank Matching" Forward-Port-Of: odoo/enterprise#127421
The “My Team” default filter now appears only on the Time Off Overview Gantt page where it is intended. This prevents employees and managers from seeing an unexpected default filter on other HR Gantt views, reducing confusion and keeping each view’s results accurate.
Original PR description
A default filter would sometimes appear on all the HR Gantt views. That is not supposed to happen as this filter is only supposed to appear on the Time Off > Overview gantt page (`hr.leave.report.calendar`) This was because the SearchModel that was supposed to be applied only for `hr.leave.report.calendar` was used for the `hrHolidaysGanttView` and `time_off_report_calendar`. This PR makes it so that the SearchModel is only applied to the required gantt view and not all of them. task-5502544
This fixes an internal automated test so it correctly accounts for archived call activity records before removing activity types. The change helps prevent false test failures and improves confidence in the mail activity and VoIP-related test suite without changing customer-facing behavior.
Original PR description
test_create_call_activity attempts to delete any 'phonecall' activity types. This is so it can test the functionality of create_call_activity when there is no existing 'phonecall' activity type. However, demo data inside voip creates an archived activity with the type mail_activity_data_call. https://github.com/odoo/enterprise/blob/cc4456ac16aeee59830db08505a27877e149f3a7/voip/demo/voip_call.xml#L4-L13 When searching for phonecall_activities the test only gets active activities. We need to alter this to fetch all. Otherwise, the test will then try to delete the activity type when there are still records using the type. opw-6443475 runbot-242850 Forward-Port-Of: odoo/enterprise#126540
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 tas
Original PR description
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 task-5411766 Forward-Port-Of: odoo/odoo#281384 Forward-Port-Of: odoo/odoo#272068
When unsetting the Available in Self Order field on a product, a traceback occurs. Steps to reproduce the error: - Install ``pos_self_order`` module with demo data - Open any Product that is available in pos > In Point of sale Tab, Unset Available in Self Order field > Save Traceback: ```py ValueError: Expected singleton: pos.config() ``` When the ``self_order_available`` field is updated, ``write()`` calls ``_send_availability_status()`` at [1]. Previously, this method only pr
Original PR description
When unsetting the Available in Self Order field on a product, a traceback occurs. Steps to reproduce the error: - Install ``pos_self_order`` module with demo data - Open any Product that is…
When unsetting the Available in Self Order field on a product, a traceback occurs. Steps to reproduce the error: - Install ``pos_self_order`` module with demo data - Open any Product that is available in pos > In Point of sale Tab, Unset Available in Self Order field > Save Traceback: ```py ValueError: Expected singleton: pos.config() ``` When the ``self_order_available`` field is updated, ``write()`` calls ``_send_availability_status()`` at [1]. Previously, this method only processed POS configurations with a ``current_session_id``, but that condition was removed in commit https://github.com/odoo/odoo/commit/22e075987cf05c5891120b86694b5312936d4def at [2]. As a result, ``_send_availability_status()`` may now call ``load_product_from_pos()`` with a POS configuration that has no current session. This eventually calls ``_get_available_pricelists()`` on an empty ``pos.config`` recordset, triggering the singleton error. [1]-https://github.com/odoo/odoo/blob/8e7732045bd465cd1a763329e4e8448de45960ad/addons/pos_self_order/models/product_product.py#L118-L120 [2]-https://github.com/odoo/odoo/blob/8e7732045bd465cd1a763329e4e8448de45960ad/addons/pos_self_order/models/product_product.py#L126 sentry-7614402869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here wh
Original PR description
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save…
Steps: - Install l10n_co module. - Set `CO company` on user. - Go to address page on portal address. - Set `Company Name`, `ID Type` and `ID Number` on the address page. Issue: - Not able to save address without any error message on the address page and in logger it raise validation error. Cause: - In address we actually do vat validation before creation/updation and if there is any issue with vat number then add it into invalid_fields instead raising any validation error, so here when user set `Company name` on address it try to create parent company and again do vat validation and it raise validation error because `ID Type` on customer is not propagated to parent when creating parent company from portal. Fix: - Skip vat validation on parent company creation from address. To-do: We also need to pass `ID type` and other accounting related values when creating parent company from customer or make them dependent like `Vat`. Issued PR: https://github.com/odoo/odoo/pull/264356 opw-6434127 Forward-Port-Of: odoo/odoo#281441 Forward-Port-Of: odoo/odoo#280859
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/5c667fedc1 [REL] 19.4.6 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/48df9225db [IMP] composer: writing an number value should override date formats [Task: 6353692](https://www.odoo.com/odoo/2328/tasks/6353692) https://github.com/odoo/o-spreadsheet/commit/48e2180e31 [FIX] index: export `CarouselFigure` [Task: 6449019](https://www.odoo.com/odoo/2328/tasks/6449019) ht
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/5c667fedc1 [REL] 19.4.6 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/5c667fedc1 [REL] 19.4.6 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/48df9225db [IMP] composer: writing an number value should override date formats [Task: 6353692](https://www.odoo.com/odoo/2328/tasks/6353692) https://github.com/odoo/o-spreadsheet/commit/48e2180e31 [FIX] index: export `CarouselFigure` [Task: 6449019](https://www.odoo.com/odoo/2328/tasks/6449019) https://github.com/odoo/o-spreadsheet/commit/1a6144752d [FIX] chart: geoChart uses same d3 projection for main and full screen chart [Task: 6395379](https://www.odoo.com/odoo/2328/tasks/6395379) https://github.com/odoo/o-spreadsheet/commit/60d40c1514 [FIX] carousel: crash on multiuser when deleting chart [Task: 6445004](https://www.odoo.com/odoo/2328/tasks/6445004) https://github.com/odoo/o-spreadsheet/commit/4e9affe04f [FIX] figures: fix movement issue with arrow keys [Task: 6374091](https://www.odoo.com/odoo/2328/tasks/6374091) https://github.com/odoo/o-spreadsheet/commit/01acbcaa9d [IMP] package: update owl to 45 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
### Problem: Background videos on `website` were not looping correctly for 3 reasons - Not all `video_providers` implemented the loop `optionsConfig`. - The `loop` optionsConfig was not enabled automatically when adding background videos - YouTube requires a `playlist` url param with the same value as the `videoID` in order to loop correctly ### Steps to reproduce: - Go to website. - Add a Snippet. - In the snippet builder options, add a background video like [1]. - Save the web
Original PR description
### Problem: Background videos on `website` were not looping correctly for 3 reasons - Not all `video_providers` implemented the loop `optionsConfig`. - The `loop` optionsConfig was not enabled…
### Problem: Background videos on `website` were not looping correctly for 3 reasons - Not all `video_providers` implemented the loop `optionsConfig`. - The `loop` optionsConfig was not enabled automatically when adding background videos - YouTube requires a `playlist` url param with the same value as the `videoID` in order to loop correctly ### Steps to reproduce: - Go to website. - Add a Snippet. - In the snippet builder options, add a background video like [1]. - Save the website. - The background video does not loop. ### Solution: This PR, - Implements the `loop` optionsConfig for more supported video providers. - Enables the `loop` optionsConfig for background videos by default - Adds the `playlist` param for YouTube video provider when `loop` optionsConfig is enabled. ### Unsupported video providers: - Loom [2] - Twitch [3] - Facebook [4] - Instagram - GoogleDrive - Dailymotion [7] ### Supported Players: - YouTube [5] - Vimeo [6] ##### Note on Dailymotion: Dailymotion supports the loop parameter on iFrame embedded videos but the behavior of playback goes against expectations set by other providers. Instead of looping through the requested video, Dailymotion will loop through an automatic "playlist" that it then goes through. This behavior is also not consistent with all videos, some videos don't seem to adhere to this norm. Since playing random videos is worse than not looping, the loop param addition is not handled by this PR. [1]: https://www.youtube.com/watch?v=sEH3pOhj0xs [2]: https://support.atlassian.com/loom/docs/embed-your-video-into-a-webpage/ [3]: https://dev.twitch.tv/docs/embed/video-and-clips/ [4]: https://developers.facebook.com/docs/plugins/embedded-video-player [5]: https://developers.google.com/youtube/player_parameters [6]: https://help.vimeo.com/hc/en-us/articles/12426486963857-How-to-add-autoplay-and-loop-parameters-to-my-video-s-embed-code [7]: https://developers.dailymotion.com/docs/add-runtime-player-parameters-web task-6431769
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order
Original PR description
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order reference is currently sent only in the `Description` field which is for internal information and is not shown to customers on their bank statements. Customers only see "MACKNET", so they cannot identify which order the payment relates to. **Expected behavior:** - Should also send the order reference to Stripe's `statement_descriptor` field, which is the field used for the customer-facing bank statement reference. - The `statement_descriptor` value must comply with Stripe's requirements: Must not contain <, >, \, ', ", or * Must contain at least one letter Maximum 22 characters **Fix:** - Pass the order reference, which should already satisfy the first two requirements based on Odoo order/invoice naming conventions opw-6424994 Forward-Port-Of: odoo/odoo#281417 Forward-Port-Of: odoo/odoo#280985
Clearing the cache in the `write` of `ir.module` caused issues when installing `website`. Having it in `create` was enough for the original use case that prompted the PR. So we remove the `write` in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None Forward-Port-Of: odoo/odoo#281465
Original PR description
Clearing the cache in the `write` of `ir.module` caused issues when installing `website`. Having it in `create` was enough for the original use case that prompted the PR. So we remove the `write` in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None Forward-Port-Of: odoo/odoo#281465
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to crash. ## Steps to produce: - Install Manufacturing - Go to settings and enable: - Subcontracting - Lots & Serial Numbers - Expiration dates - Create a product named Vegetable Salad and set Tracking to By Unique Serial Number. - In the inventory section, enable Expiration date and
Original PR description
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to…
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to crash. ## Steps to produce: - Install Manufacturing - Go to settings and enable: - Subcontracting - Lots & Serial Numbers - Expiration dates - Create a product named Vegetable Salad and set Tracking to By Unique Serial Number. - In the inventory section, enable Expiration date and configure: - Expiration Date: 10 days after receipt - Removal Date: 8 days before expiration date - Create a BoM for Vegetable salad - BoM Type: Subcontracting - Subcontractor: Chef - Component: Vegetable - Create a receipt for 2 units of Vegetable Salad from Chef - Mark it as Todo > Details > Assign serial to both lines - Set the Removal Date of the second serial number to a date earlier than today, then Save and Validate the receipt. - In the expiry warning wizard, click Proceed Except Expired and create backorder ## Observed Behavior: Creating a backorder after proceeding with the expiry warning wizard fails with the following error: `ValueError: Expected singleton: stock.move(12, 13)` ## Root cause: This issue occurs because, when the user confirms the backorder, the current picking is validated at [1]. This calls `_action_done` at [2], which in turn calls `_action_done` on the todo moves at [3]. As part of this process, `todo_moves` creates backorders at [4] and then confirms those backorder moves at [5]. During confirmation, the subcontracting manufacturing order (MO) with a serial number that has expired is split at [6], creating a new MO. This new MO then creates two backorder moves at [7]: one for the finished product and one for the component. The problem arises because `default_lot_ids` are added to the context at [8] for the expiry wizard. That same context is unintentionally propagated to the backorder wizard during backorder confirmation. As a result, the ORM assigns those lot IDs to both the component and finished product moves. This triggers the `_set_lot_ids` inverse method, which calls `_prepare_move_line_vals` at [9]. However, `_prepare_move_line_vals` is an `ensure_one` method, while `self` now contains two moves (the component move and the finished product move). Because the method expects a single record but receives two, it raises a singleton error. [1]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/wizard/stock_backorder_confirmation.py#L64 [2]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_picking.py#L1428-L1429 [3]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_picking.py#L1273 [4]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L2267-L2268 [5]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L2332 [6]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/mrp_subcontracting/models/stock_picking.py#L158 [7]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/mrp/models/mrp_production.py#L2055-L2075 [8]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/product_expiry/models/stock_picking.py#L33-L38 [9]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L679 ## Solution: Sanitize the context before opening the backorder wizard so that `default_lot_ids` from the expiry wizard are not propagated. This prevents the ORM from incorrectly assigning lot IDs to the component and finished product backorder moves, avoiding the singleton error in `_prepare_move_line_vals`. With this change, users can successfully create backorder pickings and subcontracting manufacturing orders for products that are being removed without encountering any errors opw-6390571 Forward-Port-Of: odoo/odoo#278262
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more mo
Original PR description
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is…
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more modules. ZXing's BrowserQRCodeSvgWriter draws each module at a whole number of pixels of the canvas it is given (multiple = floor(canvas / (modules + 8))), so asking it for a fixed 150x150 or 200x200 canvas leaves a leftover margin that varies with the module count. The code shrinks as soon as the module count crosses a multiple of the canvas size. opw-6399878 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281036 Forward-Port-Of: odoo/odoo#280000
With demo data, the default event TZ was not UTC. Now the test event tz is set to UTC and the test works with or without demo data. Runbot-945450 Task-6429727 Forward-Port-Of: odoo/odoo#281445
Original PR description
With demo data, the default event TZ was not UTC. Now the test event tz is set to UTC and the test works with or without demo data. Runbot-945450 Task-6429727 Forward-Port-Of: odoo/odoo#281445
Steps to reproduce: - Go to Edit mode - Go to the Theme tab - Open a color preset to customize it - Change the "Headings" color => The color of "Title" did not change in the preview By changing the tag from "h3" to "h1", the color in the preview is now correctly updated in the theme tab. "fs-4" is added to keep the previous size. task-6299680 Forward-Port-Of: odoo/odoo#279324 Forward-Port-Of: odoo/odoo#278056
Original PR description
Steps to reproduce: - Go to Edit mode - Go to the Theme tab - Open a color preset to customize it - Change the "Headings" color => The color of "Title" did not change in the preview By changing the tag from "h3" to "h1", the color in the preview is now correctly updated in the theme tab. "fs-4" is added to keep the previous size. task-6299680 Forward-Port-Of: odoo/odoo#279324 Forward-Port-Of: odoo/odoo#278056
Description ----------------- This fix ensures the allocation button appears consistently and that the parent-child relationships link correctly. Issue -------- The allocation smart button failed to appear when needed. Additionally, even when visible, creating an allocation did not properly generate the smartbuttons linking parent and child manufacturing orders together. Use Case ------------- 1. Create and confirm a manufacturing order that has a semi finished product 2. Cancel th
Original PR description
Description ----------------- This fix ensures the allocation button appears consistently and that the parent-child relationships link correctly. Issue -------- The allocation smart button failed to appear when needed. Additionally, even when visible, creating an allocation did not properly generate the smartbuttons linking parent and child manufacturing orders together. Use Case ------------- 1. Create and confirm a manufacturing order that has a semi finished product 2. Cancel the MO for the semi finished product 3. Create a new MO for the semi finished product manually 4. Go to the allocation smartbutton of the new MO and link the new MO to the final product **Task-id**: 6280980 Forward-Port-Of: odoo/odoo#269221
Steps to produce: --- - Install the Sales module. - Create a new product. - Click the edit icon on the product image. - Search for `apple`. - Select any image from the results. Issue: --- - Selecting an image raises the following JavaScript error: `TypeError: Cannot read properties of undefined (reading 'activeTab')` Root cause: --- - In [commit], `this.state.activeTab` was passed as the `activeTab` value. - [commit1] replaced `this.state.activeTab` with `this.activeTab()`, but
Original PR description
Steps to produce: --- - Install the Sales module. - Create a new product. - Click the edit icon on the product image. - Search for `apple`. - Select any image from the results. Issue: --- - Selecting an image raises the following JavaScript error: `TypeError: Cannot read properties of undefined (reading 'activeTab')` Root cause: --- - In [commit], `this.state.activeTab` was passed as the `activeTab` value. - [commit1] replaced `this.state.activeTab` with `this.activeTab()`, but this call site was not updated, causing `this.state.activeTab` to be `undefined`. Solution: --- - Replace `this.state.activeTab` with `this.activeTab()` to match the current implementation. [commit]: https://github.com/odoo/odoo/commit/7427089969ab445dc86e37d628c9c59e7c73c632 [commit1]: https://github.com/odoo/odoo/commit/2788aa7f47c2fc869f63e25d9b052d1b04f535b3 opw-6428459 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
One cannot create the record because field 'operation' is not set by the form view, but is required anyway. Fix the issue by setting a default value to field 'operation'.
Original PR description
One cannot create the record because field 'operation' is not set by the form view, but is required anyway. Fix the issue by setting a default value to field 'operation'.
Steps to reproduce: 1. Install Calendar 2. Create a meeting in Calendar in form view 3. Set the video link on it 4. Turn on the debug mode 5. Now, clear the video link Issue: - Traceback ``` Uncaught Promise > Invalid props for component 'CopyButton': 'content' is not a string or object or function ``` Cause: - The 'CopyButton' component expect content to be a string, object or function but receives false. It does not happen in previous versions because in the refector https:/
Original PR description
Steps to reproduce: 1. Install Calendar 2. Create a meeting in Calendar in form view 3. Set the video link on it 4. Turn on the debug mode 5. Now, clear the video link Issue: - Traceback ``` Uncaught…
Steps to reproduce: 1. Install Calendar 2. Create a meeting in Calendar in form view 3. Set the video link on it 4. Turn on the debug mode 5. Now, clear the video link Issue: - Traceback ``` Uncaught Promise > Invalid props for component 'CopyButton': 'content' is not a string or object or function ``` Cause: - The 'CopyButton' component expect content to be a string, object or function but receives false. It does not happen in previous versions because in the refector https://github.com/odoo/odoo/commit/c2f34517b2f9832a498981d0fa17ec39b9739cb6 set the `videocall_location` to false instead of empty string like before https://github.com/odoo/odoo/blob/499420f7062ab467ff6f50b30c547e54c35ae1e9/addons/web/static/src/core/copy_button/copy_button.js#L14 - but any field using the `CopyClipboardChar/CopyClipboardURL` widget passes its raw field value straight through as content. An empty char/text field is represented as false, so whenever such a field becomes empty, CopyClipboardField hands `false` to CopyButton, which fails prop validation (debug mode). Solution: - Fix it at the source: CopyClipboardField's template now falls back to an empty string when the field value is falsy, so CopyButton never receives false but a valid string. opw-6360936 Forward-Port-Of: odoo/odoo#280363 Forward-Port-Of: odoo/odoo#275236
#### Description of the issue this PR addresses: - The predicate loop kept climbing ancestors above the editable root when no match was found inside it. The later containment check would discard such a match anyway, so the predicate should never run outside the editable in the first place. - This ran the predicate on at least 14 unnecessary ancestors up to `<html>`, costly if the predicate is expensive. Stop the search at the editable boundary instead. - `movenode_plugin` calls closestElement
Original PR description
#### Description of the issue this PR addresses: - The predicate loop kept climbing ancestors above the editable root when no match was found inside it. The later containment check would discard such a match anyway, so the predicate should never run outside the editable in the first place. - This ran the predicate on at least 14 unnecessary ancestors up to `<html>`, costly if the predicate is expensive. Stop the search at the editable boundary instead. - `movenode_plugin` calls closestElement on every mousemove, so its predicate was needlessly re-evaluated on those 14+ ancestors on every single mouse move. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280011
The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280368
Original PR description
The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280368
A default filter would sometimes appear on all the HR Gantt views. That is not supposed to happen as this filter is only supposed to appear on the Time Off > Overview gantt page (`hr.leave.report.calendar`) This was because the SearchModel that was supposed to be applied only for `hr.leave.report.calendar` was used for the `hrHolidaysGanttView` and `time_off_report_calendar`. This PR makes it so that the SearchModel is only applied to the required gantt view and not all of them. task-55
Original PR description
A default filter would sometimes appear on all the HR Gantt views. That is not supposed to happen as this filter is only supposed to appear on the Time Off > Overview gantt page (`hr.leave.report.calendar`) This was because the SearchModel that was supposed to be applied only for `hr.leave.report.calendar` was used for the `hrHolidaysGanttView` and `time_off_report_calendar`. This PR makes it so that the SearchModel is only applied to the required gantt view and not all of them. task-5502544
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test: ``` show banner for new message after thread was read from another device Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))" (Timeout of 10 seconds). Found 0 instead. ``` This happens because a message received while the composer h
Original PR description
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test:
```
show banner for new message after thread was read from another device
Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))"
(Timeout of 10 seconds). Found 0 instead.
```
This happens because a message received while the composer has the focus is marked as read whatever the scroll position, while the counter the banner reads is frozen only when the conversation is scrolled to the bottom too. The counter therefore goes up for a scrolled up user, and back to zero as soon as the read reaches the server.
This commit marks a received message as read only when the conversation is scrolled to the bottom, as the other automatic reads already do.
https://runbot.odoo.com/odoo/error/945671
Forward-Port-Of: odoo/odoo#281488After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414 Forward-Port-Of: odoo/odoo#279964
Original PR description
After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414 Forward-Port-Of: odoo/odoo#279964
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of
Original PR description
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device…
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of pos_reference only, which is the receipt counter each device keeps in its own browser local storage and which restarts at 1. Both devices therefore name their first order "<config> - 000001", and _get_tbai_seq_from_name derives the same SerieFactura and NumFactura for the two of them. Fix: Send pos_reference instead. It is the number printed on the customer receipt and it also holds the device identifier, allocated by the device sequence of the config, which is what makes it unique. The device part ends up as the series and the counter as the number, so the numbering stays sequential inside the series of each device, and the series still starts with the year the duplicate check is made on. Both stay well below the 20 characters SerieFactura and NumFactura are limited to. The name of the refunded document is taken from the same helper, so a credit note cannot reference a number that was never registered. The pos.order name itself is not unique on any version from 19.0 on, but it cannot be changed in stable. opw-6442837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280621
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource
Original PR description
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the…
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource Calendar on the company (this is required and must differ from the employee's flexible working schedule). - Attempt to create a Time Off request for the employee. **Cause:** https://github.com/odoo/odoo/blob/5e865aeec854ca012dc5537f36b2e626ee39cf0b/addons/l10n_fr_hr_holidays/models/hr_leave.py#L17-L27 `_l10n_fr_leave_applies()` considers an empty employee calendar different from the company calendar. This sends flexible leaves to `_get_fr_date_from_to()`, which requires attendance rows and rejects the request. **Solution:** We need to require a concrete employee calendar before applying the French part-time calendar adjustment, leaving flexible employees to the core flexible-duration computation. opw-6417220 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280288
Version: -------- - saas-19.4+ Steps to reproduce: ------------------- - Install `stock` module - Create a storable product and set 10 units on hand - Create a delivery for 10 units, confirm it - Under Operation tab click into view button which is optional hide - Delete the move line and save Issue: ------ After deleting the stock move line, the move is no longer reserved, but the **Reserve** button does not reappear on the delivery. Cause: ------ Saving the Detailed Operat
Original PR description
Version: -------- - saas-19.4+ Steps to reproduce: ------------------- - Install `stock` module - Create a storable product and set 10 units on hand - Create a delivery for 10 units, confirm it -…
Version: -------- - saas-19.4+ Steps to reproduce: ------------------- - Install `stock` module - Create a storable product and set 10 units on hand - Create a delivery for 10 units, confirm it - Under Operation tab click into view button which is optional hide - Delete the move line and save Issue: ------ After deleting the stock move line, the move is no longer reserved, but the **Reserve** button does not reappear on the delivery. Cause: ------ Saving the Detailed Operations form writes both `move_line_ids` and `quantity` in the same `stock.move.write()` call. `BaseModel.write()` applies field values according to each field's `write_sequence`. `move_line_ids` is written first (`write_sequence = 20`): https://github.com/odoo/odoo/blob/9eca8f23bfa24e5dc4bf70a6dd7be2e6aff7a91d/odoo/orm/fields_relational.py#L603 After this [commit](https://github.com/odoo-dev/odoo/commit/7c2880c2ab43d70dc51bdba499eacc17c95af46c ) in saas-19.4, `quantity` is written afterwards (`write_sequence = 25`) so that lot updates happen before the quantity inverse: As a result: 1. Deleting the move line triggers `stock.move.line.unlink()`, which immediately calls `_recompute_state()`. https://github.com/odoo/odoo/blob/9eca8f23bfa24e5dc4bf70a6dd7be2e6aff7a91d/addons/stock/models/stock_move_line.py#L584 2. At that moment, `quantity` has not yet been updated, so `_recompute_state()` still sees the previous reserved quantity and leaves the move in the `assigned` state. https://github.com/odoo/odoo/blob/9eca8f23bfa24e5dc4bf70a6dd7be2e6aff7a91d/addons/stock/models/stock_move.py#L2488-L2489 3. Afterwards, the `quantity` inverse updates the reservation, but no second state recomputation is triggered, leaving the move and the picking state inconsistent. (and thus `show_check_availability` on the picking, which depends on move state) stays out of sync. 3. `quantity` is written afterwards and its inverse (`_set_quantity`) updates the reservation, but nothing recomputes the state again, so the move (and thus `show_check_availability` on the picking, which depends on move state) stays out of sync. Before [commit](https://github.com/odoo-dev/odoo/commit/7c2880c2ab43d70dc51bdba499eacc17c95af46c ) `quantity` was written before `move_line_ids`, so when `unlink()` triggered `_recompute_state()`, the quantity had already been updated and the move state was computed correctly. Fix: ---- When `move_line_ids` is modified through `stock.move.write()`, mark the move for state recomputation, similarly to `move_orig_ids`. The actual `_recompute_state()` call is deferred until after `super().write()` completes, ensuring it runs with all written fields (including `quantity` and its inverse) already updated, regardless of the internal field write order. --- opw-6359640 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Since #247162, H11 is used in Odoo. It was added in the packages.txt used for the raspberry pi but not in the requirements.txt for the windows version. As we changed the version of the IoT to 19.4, new IoT and the ones that update will crash. This let the next image we generate to get the package. opw-6449851 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280825 Forward-Port-Of: odoo/odoo#280694
Original PR description
Since #247162, H11 is used in Odoo. It was added in the packages.txt used for the raspberry pi but not in the requirements.txt for the windows version. As we changed the version of the IoT to 19.4, new IoT and the ones that update will crash. This let the next image we generate to get the package. opw-6449851 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280825 Forward-Port-Of: odoo/odoo#280694
If two print jobs arrive at the same time, the second one overwrites the `session_id` stored on the driver. This prevents the pos from linking jobs sent with their result (callbacks). task-6449868
Original PR description
If two print jobs arrive at the same time, the second one overwrites the `session_id` stored on the driver. This prevents the pos from linking jobs sent with their result (callbacks). task-6449868
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8
Original PR description
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1)…
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8. *Create Invoice* again, with a **Timesheets Period of 01/06 → 31/07** ### Current behavior The invoice bills **9 h**: the 4.5 h that were invoiced and not credited are billed a second time. ### Expected behavior The invoice bills **4.5 h** — the quantity delivered minus the quantity invoiced. ### Cause of the issue Posting a partial credit note clears `timesheet_invoice_id` on every timesheet the reversed invoice had linked (`sale_timesheet/models/account_move.py`, `action_post`), because a credit note carries a quantity and never a set of timesheets, so there is no way to tell which hours it credited. All of those hours therefore become candidates again in `_recompute_qty_to_invoice`, which assigns their sum to `qty_to_invoice` without comparing it to what is still due on the line. ### Fix Timesheet links cannot express a partially invoiced timesheet, so they are used only to select the hours a period concerns, while the quantity that may still be billed is `qty_delivered - qty_invoiced`. The period lookup is capped by that remainder, and kept at zero or above so that an over-invoiced line is corrected by a deliberate credit note rather than as a side effect of invoicing a period. ### Tests Five tests are added to `addons/sale_timesheet/tests/test_sale_timesheet.py`. Three of them fail without the fix: | test | without the fix | | --- | --- | | `test_period_invoice_does_not_rebill_refunded_invoice_hours` | `9.0 != 4.5` | | `test_period_invoice_after_refund_is_computed_per_line` | `4.0 != 1.5` | | `test_period_invoice_after_refund_of_an_over_invoiced_line` | `8.0 != 1.0` | The other two cover behaviour that is not exercised today and that the fix must not break: an over-invoiced line (which must be left out rather than credited, and must not prevent the other lines of the order from being invoiced) and the reversed invoice's own `invoice_date`, which must not influence the quantity billed for a period. The full `sale_timesheet` suite passes (86 tests). Forward-Port-Of: odoo/odoo#281065 Forward-Port-Of: odoo/odoo#280536