Daily updates from Odoo
Thursday, July 30, 2026
19 changes · 18.0
Resolved issues and error corrections
Cancelled restaurant orders are now removed from the kitchen display's in-progress count. This keeps preparation totals accurate for staff and avoids confusion after orders are cancelled during POS closing.
Original PR description
Step to reproduce: - install pos_restaurant with demo - start a restaurant pos, in a other tab, open the kitchen display app - notice the `in progress` count to be X in kanban view - from pos, send a…
Step to reproduce: - install pos_restaurant with demo - start a restaurant pos, in a other tab, open the kitchen display app - notice the `in progress` count to be X in kanban view - from pos, send a order to kitchen - in other tab, notice the `in progress` count of to be X+1 - close the pos, when asked, cancel the order Observation: - notice, in preparation display, `in progress` stays same, but as we cancelled the order, `in progress` should be updated from X+1 to X Cause: - the count comes from computed field, `order_count` which considers `orderline.product_quantity > 0` for counting it as `in progress` https://github.com/odoo/enterprise/blob/2027db92c8b2b2c90983fc663b2e4c5c4ca1e83f/pos_preparation_display/models/preparation_display.py#L184-L187 - `orderline.product_quantity` is unaffected by cancelling the order Fix: - after a order is cancelled the linked orderline's `product_cancelled` is updated, so a difference of `product_quantity` and `product_cancelled` tell us whether a order is in `in progress` or not opw-6414253
Polish JPK tax exports now use the vendor bill reference in the purchase document field when it is available. This improves alignment with Polish reporting requirements and helps exported XML files reflect supplier documentation more accurately.
Original PR description
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting >…
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting > Reporting > Tax Report and select `This Month`. - From the dropdown, click `JPK` > `Export XML`. - Open the generated XML file and observe the `DowodZakupu` field. **Observation:** `DowodZakupu` contains the vendor `Bill Number` even when a `Bill Reference` is set. **Root Cause:** At [1], `DowodZakupu` is populated only with the vendor `Bill number`(`move_name`) instead of using the `Bill reference`(`ref`) when available. **Fix:** This commit ensures `DowodZakupu` contains the `Bill Reference` when it is available in JPK exports. **Reference:** https://www.podatki.gov.pl/media/eqrn3dey/broszura-jpk_vat-z-deklaracj%C4%85-od-1-lutego-2026-r-en.pdf (page 41) [1]: https://github.com/odoo/enterprise/blob/4b0404058b280136f6865090562f95e18d4d7e0b/l10n_pl_reports/data/jpk_export_templates.xml#L208 opw-6299827 Forward-Port-Of: odoo/enterprise#121117
Basic users can now open the spreadsheet creation window in Documents even when they do not have access to spreadsheet templates. This removes an inconsistent restriction and lets them create empty spreadsheets from the Documents kanban view, matching what was already possible from an existing spreadsheet view.
Original PR description
A basic user can access the document app and create all types of documents from the kanban view except for the spreadsheets because it requires an access to the templates. While the user cannot interact with the templates, they should have the possibility to create an empty spreadsheet. Note that it can already be done coming from the view of a spreadsheet! This revision ensures that the user can indeed access the spreadsheet creation modal even if they don't have access to the spreadsheet templates. Task-6364964
Step To Reproduce: * Install the French Localization and Accounting modules. * Create and confirm two vendor bills with 20% tax, one dated in the previous month and one in the current month. * Switch the database language to French (Français). * Confirm the previous month's tax return closing entry. * Confirm the current month's tax return closing entry, enter a refund request, and submit it. * Notice that the generated refund request journal entry contains incorrect debit/credit lines.
Original PR description
Step To Reproduce: * Install the French Localization and Accounting modules. * Create and confirm two vendor bills with 20% tax, one dated in the previous month and one in the current month. * Switch…
Step To Reproduce: * Install the French Localization and Accounting modules. * Create and confirm two vendor bills with 20% tax, one dated in the previous month and one in the current month. * Switch the database language to French (Français). * Confirm the previous month's tax return closing entry. * Confirm the current month's tax return closing entry, enter a refund request, and submit it. * Notice that the generated refund request journal entry contains incorrect debit/credit lines. Reason: The refund request journal entry is generated incorrectly when the database language is set to French because the implementation expects the account labels in French. As a result, the label comparison fails, causing incorrect journal entry lines to be generated. The issue does not occur when the database language is set to English. Solution: Apply the required translation fix in the French file so that the expected account labels are correctly resolved during tax return submission. This is a temporary workaround until the underlying issue is addressed. Note: The current implementation relies on matching translated account labels((https://github.com/odoo/enterprise/blob/18.0/l10n_fr_reports/wizard/l10n_fr_send_vat_report.py#L438)), which is not an ideal approach. I discussed this with the R&D team, and they confirmed that implementing a proper fix requires a deeper understanding of the complete flow and will take more time. Therefore, this PR provides a temporary translation-based workaround to resolve the customer's issue. opw-6402308
In this commit: ------------------- - Fixed an issue when `disallowLineQuantityChange` is enabled. In this case, a negative quantity line can represent a newly added line rather than a removed one. - Updated the logic to determine whether a negative-quantity line should be treated as a new or removed line based on the synchronization status of the order. If the order has not been synced yet, the negative-quantity line is treated as a new line. task: 6326042 Related PR: https://github.c
Original PR description
In this commit: ------------------- - Fixed an issue when `disallowLineQuantityChange` is enabled. In this case, a negative quantity line can represent a newly added line rather than a removed one. - Updated the logic to determine whether a negative-quantity line should be treated as a new or removed line based on the synchronization status of the order. If the order has not been synced yet, the negative-quantity line is treated as a new line. task: 6326042 Related PR: https://github.com/odoo/enterprise/pull/120410
**Steps to reproduce:** - Go to the Discuss app - Send an image in a conversation - Open the image in full view - Click on the download button in the top right corner - Error: 405 Method Not Allowed **Issue:** The issue comes from commit [1], which changed the `FileViewer` to send a POST request for downloads. However, the Discuss routes `/discuss/channel/...` in `odoo/addons/mail/controllers/discuss/binary.py` only accept `methods=["GET"]`, so the download fails. These routes no lon
Original PR description
**Steps to reproduce:** - Go to the Discuss app - Send an image in a conversation - Open the image in full view - Click on the download button in the top right corner - Error: 405 Method Not Allowed **Issue:** The issue comes from commit [1], which changed the `FileViewer` to send a POST request for downloads. However, the Discuss routes `/discuss/channel/...` in `odoo/addons/mail/controllers/discuss/binary.py` only accept `methods=["GET"]`, so the download fails. These routes no longer exist in 19.0, where they have been replaced by `/web/image/` (see commit [2]). **Fix:** Add "POST" to the allowed methods of the discuss routes. [1] https://github.com/odoo/odoo/commit/fb152985f4b860a5abef9ed0ba72c168a3c51599 [2] https://github.com/odoo/odoo/commit/f96a995e245080421cfb7b3246d2635824eb2edb opw-6390697
Issue ----- In store pick up does not work. Steps to reproduce ----- - Enable in store pick up - Go to website - Add a product to cart - Go to checkout - Select the pickup delivery method & choose a pickup point - Confirm > Error: "Sorry, it is not possible to ship your order. Please choose a store to pick up your order." Cause ----- 7971be1 made it so confirming the order calls `_set_delivery_method`, which in turn resets the value of the selected location https://github.
Original PR description
Issue ----- In store pick up does not work. Steps to reproduce ----- - Enable in store pick up - Go to website - Add a product to cart - Go to checkout - Select the pickup delivery method & choose a pickup point - Confirm > Error: "Sorry, it is not possible to ship your order. Please choose a store to pick up your order." Cause ----- 7971be1 made it so confirming the order calls `_set_delivery_method`, which in turn resets the value of the selected location https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/website_sale/models/sale_order.py#L670 ----- Ticket: opw-6425014
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used
Original PR description
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used while preserving the existing validation against empty or whitespace-only names. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273593
Prevent links inserted by users from harming SEO or being used for spam. Links created by visitors are marked as "user generated content" and "no follow". Task-5182753
Original PR description
Prevent links inserted by users from harming SEO or being used for spam. Links created by visitors are marked as "user generated content" and "no follow". Task-5182753
**PROBLEM** Before this PR, there was no way to handle invoices sent to clients depending from a JST/LGU (local government unit). This PR add support for it. opw-6095581
Original PR description
**PROBLEM** Before this PR, there was no way to handle invoices sent to clients depending from a JST/LGU (local government unit). This PR add support for it. opw-6095581
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the corresponding Purchase Orders, then confirm the merged PO 4. Validate the dropship transfer Issue stock.picking.sale_id is a Many2one (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/sale_stock/models/stock.py#L99) computed from procurement.group.sale_id, an
Original PR description
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the…
Steps to reproduce 1. Create two products and assign the same vendor to both in the Purchase tab 2. Create two Sales Orders using the dropship route (one product per order) 3. Generate and merge the corresponding Purchase Orders, then confirm the merged PO 4. Validate the dropship transfer Issue stock.picking.sale_id is a Many2one (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/sale_stock/models/stock.py#L99) computed from procurement.group.sale_id, and stock.picking.group_id is a stored related on move_ids.group_id (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/stock/models/stock_picking.py#L186). A single picking can therefore only resolve to one SO. _create_picking (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/purchase_stock/models/purchase_order.py#L290) builds one picking per PO and _prepare_stock_moves assigns every move the merged PO's group_id (https://github.com/odoo/odoo/blob/18c3a034b7d3772baca62d8d86efba2ca15f17b0/addons/purchase_stock/models/purchase_order_line.py#L307), so when a merged dropship PO carries lines from multiple SOs every move lands in one picking under the PO group. Only one SO gets linked and the others stay "not fully delivered" even after validation. Solution Override PurchaseOrderLine._prepare_stock_moves to set group_id to the SO's procurement_group_id when sale_line_id is set, so each dropship move is created in its originating SO's procurement group. Override PurchaseOrder._create_picking to detect dropship POs whose order lines span more than one SO and create one picking per SO group by calling _prepare_picking and _create_stock_moves per group. picking.group_id then resolves to the SO group via the stored related field, picking.sale_id points to the right SO, and delivery_status updates correctly on validation. opw-6094608
The timesheet list view is sorted newest-first (date desc, id desc), but new entries created via the New button were inserted at the bottom due to editable="bottom". Switch to editable="top" so a new line appears next to the newest existing entry, improving user experience. This was the case at least in 15.0 so this PR recovers the earlier, correct variant. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
The timesheet list view is sorted newest-first (date desc, id desc), but new entries created via the New button were inserted at the bottom due to editable="bottom". Switch to editable="top" so a new line appears next to the newest existing entry, improving user experience. This was the case at least in 15.0 so this PR recovers the earlier, correct variant. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Issue: Outstanding credits/debits from a branch don't appear on the main company and inversely. Cause : From odoo/odoo#255875 outstanding credits/debits are limited by company to prevent different company issues on validation. However, this error is raised for `account.move` having different root companies. Which allow move from different branches of the same company. Steps to reproduce: - create a company and a branch - in the main company create a customer payment and valid it - in
Original PR description
Issue: Outstanding credits/debits from a branch don't appear on the main company and inversely. Cause : From odoo/odoo#255875 outstanding credits/debits are limited by company to prevent different company issues on validation. However, this error is raised for `account.move` having different root companies. Which allow move from different branches of the same company. Steps to reproduce: - create a company and a branch - in the main company create a customer payment and valid it - in the branch, create an invoice for the same customer and confirm it Current behavior: - the outstanding payment from the main company doesn't appear on the branch invoice, However, it's possible to reconcile it from the Journal entry view Expected behavior: - the outstanding payment from the main company appears on the branch invoice, opw-6140689
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/54a18dce0a [REL] 18.0.77 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/205a28308e [FIX] ui_sheet: `getCellWidth` getter for non-active sheet [Task: 6409426](https://www.odoo.com/odoo/2328/tasks/6409426) 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> C
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/54a18dce0a [REL] 18.0.77 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/205a28308e [FIX] ui_sheet: `getCellWidth` getter for non-active sheet [Task: 6409426](https://www.odoo.com/odoo/2328/tasks/6409426) 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>
_(updates on July-17th and July-28th for points 2. and 3. in `hr_expense`)_ # Introduction **1\.** A fix to `hr_org_chart` was initially proposed. I think it is mergeable because it fixes the user-experience properly like expected in Odoo standard. Other commits are suggested to `hr_expense`. They were designed to allow more flexibility in the management of `hr_employee.company_id` (in multi-company context) and allow not to duplicate the `hr.employee` of each companies of the `res.user
Original PR description
_(updates on July-17th and July-28th for points 2. and 3. in `hr_expense`)_ # Introduction **1\.** A fix to `hr_org_chart` was initially proposed. I think it is mergeable because it fixes the…
_(updates on July-17th and July-28th for points 2. and 3. in `hr_expense`)_ # Introduction **1\.** A fix to `hr_org_chart` was initially proposed. I think it is mergeable because it fixes the user-experience properly like expected in Odoo standard. Other commits are suggested to `hr_expense`. They were designed to allow more flexibility in the management of `hr_employee.company_id` (in multi-company context) and allow not to duplicate the `hr.employee` of each companies of the `res.users`. **2\.** The [FIX] silences a multi-company access error when searching for Expense validators => it seems safe **3\.** The [IMP] largely allow more flexibility for a "Expense: Team Approver" when creating expenses on behalf of its subordinates # 1. in hr_org_chart [FIX] Prevents multi-company error when recursively searching for ancestors. <img width="1035" height="789" alt="image" src="https://github.com/user-attachments/assets/d5517f79-7efc-4223-ae77-0af8b25a3d1e" /> ### Issue description In a multi-company environment, when one of the `hr_employee.company_id` of a hierarchy is not in the allowed companies of a Manager's `res_users.company_ids`, this Manager can view `hr.employee` in the list view but cannot open their forms. This happens when: - `hr_org_chart` module is installed - the Org Chart is displayed on the 1st page of the `hr.employee` form, like when the HR settings "Skills Management" is disabled (in `res.settings`) => thus the whole form becomes inaccessible from the manager When a `hr.employee` form is opened, a multi-company access error is thrown to him, even if the `company_id` of the opened `hr.employee` is in the user's `res_users.company_ids`, because of the hierarchy's `company_id`. It should be expected that the part of the Org Chart which is not allowed to be seen would just be hidden. ### Steps to reproduce Data setup: - Employee "A" in company A - Manager "M" in company A, manager of "Employee A" - Manager of manager "MM" in company A, manager of "Manager M" - And now, in company B (let's say a Holding), the "Director" is manager of "Manager MM" - "Manager M" is only given access access to Company A - the module "hr_org_chart" is installed Actions: - Login with Manager M - Browse to Employees list and try and open the form of "Employee A" (up to tab _"Professional information"_, if it is not the 1st of the notebook) ### Proposed fix This PR re-uses the already existing method `_check_employee` which contains all the logic to solve the issue. Maybe the call to this method was forgotten? This PR simply call this method when finding an ancestor, in the controller of `hr_org_chart`. This fix is thus very limited to the call to the public method `hr_org_chart.get_org_chart()` made by the Org Chart widget. ### Desired behavior after PR is merged The part of the Org Chart not allowed to be seen by "Manager M" is hidden. # 2. hr_expense [FIX] <img width="541" height="415" alt="image" src="https://github.com/user-attachments/assets/d594815b-2b77-4088-878b-9b192b64d6a3" /> ### Issue description As an employee, I click on the button "View Report" on my expense. I get a multi-company access error, preventing me to view and edit my expense report. This is because the manager of the department I belong is in a company I'm not allowed to see. This can also happen just when opening my Expense (instead of Expense Report). ### Current behavior before this PR The employee is blocked to continue editing its Expense or to submit it to a Report. ### Current behavior after this PR The employee can edit and submit its Expense no matter the `company_id` of its hierarchy. Technically: the `can_approve` field on the expense sheet uses a localized `.sudo()` method to bypass multi-company limits when searching if the current user is a validator. # 3. hr_expense [IMP] <img width="1028" height="549" alt="image" src="https://github.com/user-attachments/assets/1096c0d4-d025-46a9-8559-6bab5de71577" /> ### Improvement summary In multi-company environment, allow a "Expense: Team Approver" to create Expenses for its subordinates (`hr_expense.employee_id`) **no matter the `hr_employee.company_id` of its subordinates**. The domain of `hr_expense.employee_id` keeps the security of `check_company=True` => thus the Manager only sees `hr.employee` having their `company_id` in the manager's allowed companies (`res_users.company_ids`). ### Current behavior before this PR Context: a 8-companies environment where the `hr.employee` of each hierarchy chains are splitted in many different companies, like: - top-level (admin board): 1 company - middle management: approx. 2 companies - down level: the other companies The "down level" have `hr.employee` but no `res.users`. The "middle management" have `res.users` and must create the Expenses of their "down level" subordinates on their behalf. Issue: as a manager, as per Odoo proposal, I need to have a `hr.employee` in the same company of my subordinates to be able to create Expense of their behalf. However, this is very inconvenient because as a Manager, I can have employees in various companies. And my own manager it not in the same company than me, so the same issue applies recursively. ### Behavior after this PR is merged The domain of the field `expense_id.employee_id` is more permissive. As a Manager, it allows me to select the Employee I manage in my active company, no matter if I have or not myself a `hr.employee` in this company. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the fro
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#278774 Forward-Port-Of: odoo/odoo#278667
Original PR description
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#278774 Forward-Port-Of: odoo/odoo#278667
Documentation and clarification updates
Miscellaneous changes
Backport of #275640 Despite resolving the conflicts (file moved) this version also checks the python version since PyUnstable_Type_AssignVersionTag does not exists in python 3.10 To be safer, the whole logic is skipped if python < 3.13 Forward-Port-Of: odoo/odoo#277697
Original PR description
Backport of #275640 Despite resolving the conflicts (file moved) this version also checks the python version since PyUnstable_Type_AssignVersionTag does not exists in python 3.10 To be safer, the whole logic is skipped if python < 3.13 Forward-Port-Of: odoo/odoo#277697