Daily updates from Odoo
Monday, March 30, 2026
42 changes · saas-19.1
Enhancements to existing features
This update automatically updates the Uruguayan tax authority (DGI) status for electronic stock pickings, ensuring compliance. When a picking is rejected by the DGI, the system now logs the issue and notifies users for manual review, improving accuracy and reducing manual effort.
Original PR description
This pull request introduces an automated process to periodically update the DGI (Dirección General Impositiva) state for Uruguayan electronic stock pickings, along with improvements to error…
This pull request introduces an automated process to periodically update the DGI (Dirección General Impositiva) state for Uruguayan electronic stock pickings, along with improvements to error handling and logging when a picking is rejected. The main changes are the addition of a scheduled cron job, enhanced logging, and user notifications for rejected pickings. **Automated DGI State Updates:** * Added a new scheduled cron job (`ir_cron_update_dgi_state_pickings`) that runs every 10 minutes to update the DGI state of stock pickings with electronic documents in the "received" state. (`l10n_uy_edi_stock/data/ir_cron.xml`, `l10n_uy_edi_stock/__manifest__.py`) [[1]](diffhunk://#diff-36f19bab7c2edeb0f43a1db1639b72e8508deed19652e0b1142ebfce688b9d3eR1-R11) [[2]](diffhunk://#diff-370a6cfd5890d6504958deb4a225d69ec84e84fa59deeeb52c96a849f3fdfc22R14) * Implemented the `_l10n_uy_edi_stock_cron_update_dgi_state` method in `stock_picking.py` to process batches of pickings and trigger itself again if more records remain. (`l10n_uy_edi_stock/models/stock_picking.py`) **Error Handling and Notifications:** * Enhanced the `l10n_uy_edi_action_update_dgi_state` method to log rejected pickings and post a message in the chatter to notify users when a picking has been rejected by DGI, prompting manual review and correction. (`l10n_uy_edi_stock/models/stock_picking.py`) * Introduced logging setup for the module to support the new logging functionality. (`l10n_uy_edi_stock/models/stock_picking.py`) [[1]](diffhunk://#diff-108d31170c95f307accd45410f9a98bd16ce0413932fab4732eb764d75d3e260R2) [[2]](diffhunk://#diff-108d31170c95f307accd45410f9a98bd16ce0413932fab4732eb764d75d3e260R14) Forward-Port-Of: odoo/enterprise#109518
Resolved issues and error corrections
A recent update caused partner names in the approval request report to overflow, making the report unreadable. This fix adds a column limit to the partner field, ensuring all data displays correctly and preventing visual errors. This improves the report's usability and data presentation.
Original PR description
step to reproduce: - install "approval" with demo data - have a partner with name length > 63 - open one of the approvals and change its type to "general approval" - add this partner in contact field - print approval request report Observation: - the partner overflows out of report Fix: - we limit the partner field with `col-9`. For a safe measure i have added `col-9` for `request_owner_id` and `approver_ids` **Before** <img width="1057" height="326" alt="image" src="https://github.com/user-attachments/assets/a8eea789-5cc7-4658-88b5-78751759d043" /> **After** <img width="994" height="330" alt="image" src="https://github.com/user-attachments/assets/bfbc061b-a6e0-4593-a3cc-c85cb81db6e2" /> opw-6005752 Forward-Port-Of: odoo/enterprise#111130
This update fixes an issue where failed quality checks weren't correctly splitting stock moves, leading to inaccurate demand calculations. The fix ensures that when a partial failure occurs, the stock move is divided accurately, maintaining correct inventory levels. This improves the reliability of quality control processes and prevents stock discrepancies.
Original PR description
**Steps to reproduce:** * Install the `quality_control` module. * Create a storable product. * Configure a Quality Control Point: * Set Control per : Quantity. * Set Operation Type to Receipts. * Set…
**Steps to reproduce:** * Install the `quality_control` module. * Create a storable product. * Configure a Quality Control Point: * Set Control per : Quantity. * Set Operation Type to Receipts. * Set Product to the created product. * Create a Receipt for the product with a demand of 5 units. * Confirm the receipt and mark it as To Do. * Click on the Quality Check button. * Click on Fail and set the failed quantity to 3. * Click on Confirm. **Observed behavior:** * A new stock move is created for the failed quantity. * The original move is split incorrectly: * First move: 2 `product_uom_qty` and 2 `quantity`. * Second move: 2 `product_uom_qty` and 3 `quantity`. * The failed move has a demand of **2** instead of **3**. **Cause:** * Clicking on *Quality Check* triggers `check_quality`, which opens the wizard `action_open_quality_check_wizard`: https://github.com/odoo/enterprise/blob/90567af2703a3928c35814a0c4862b4cd98b8432/quality_control/models/stock_picking.py#L79-L82 * Clicking on *Fail* triggers `do_fail`, opening the confirmation wizard: https://github.com/odoo/enterprise/blob/90567af2703a3928c35814a0c4862b4cd98b8432/quality_control/wizard/quality_check_wizard.py#L85-L88 * Clicking on *Confirm* triggers `confirm_fail`, which calls `_move_line_to_failure_location`: https://github.com/odoo/enterprise/blob/90567af2703a3928c35814a0c4862b4cd98b8432/quality_control/wizard/quality_check_wizard.py#L97 * In `_move_line_to_failure_location`, a new stock move is created for the failed quantity: https://github.com/odoo/enterprise/blob/90567af2703a3928c35814a0c4862b4cd98b8432/quality_control/models/quality.py#L480 * The demand quantity is computed using the minimum of the failed quantity and the move line quantity. * This leads to an incorrect demand of *2* instead of *3*. * However, the move line quantity was already reduced by the failed quantity: https://github.com/odoo/enterprise/blob/90567af2703a3928c35814a0c4862b4cd98b8432/quality_control/models/quality.py#L472 **Fix:** * Ensure that partial failures properly split stock moves with correct `product_uom_qty` and `quantity` values. --- opw-5492095 Forward-Port-Of: odoo/enterprise#112298 Forward-Port-Of: odoo/enterprise#107493
This update fixes a warning displayed in the tax report when vendor bills have expense lines with different vehicle assignments. The change allows for more flexibility in how tax lines are matched, ensuring accurate reporting even with mixed vehicle expense lines. This improves the reliability of financial reporting.
Original PR description
**Steps to reproduce:** * Install the **account** and **fleet** modules. * Create a vendor bill with two expense lines using the same tax. * Assign a vehicle_id to one line but leave the other…
**Steps to reproduce:** * Install the **account** and **fleet** modules. * Create a vendor bill with two expense lines using the same tax. * Assign a vehicle_id to one line but leave the other without a vehicle. * Confirm the vendor bill. * Go to **Accounting > Reporting > Tax Report** and Go to `Account > Tax` report. **Observed behavior:** * The tax report shows: 'This report contains inconsistencies. The affected lines are marked with a warning.' **Cause:** * The `_get_extra_query_base_tax_line_mapping()` override forced vehicle_id matching using `COALESCE(base_line.vehicle_id, 0) = COALESCE(account_move_line.vehicle_id, 0)`. * When lines share a tax but have different vehicle_id values (one set, one NULL), Odoo creates a single tax line with `vehicle_id = NULL`. * The strict COALESCE constraint prevented this tax line from matching either base line (NULL ≠ vehicle_id and NULL ≠ NULL when coalesced to 0), causing the inconsistency. **Fix:** * Changed the constraint to only enforce vehicle_id matching when both the base line and tax line have a vehicle_id set. * If either side is NULL, the match is allowed, letting shared tax lines work correctly across mixed vehicle/non-vehicle expense lines. opw-5956645 Forward-Port-Of: odoo/enterprise#112313 Forward-Port-Of: odoo/enterprise#110616
This update resolves an issue where web_studio would generate an error when users attempted to save reports with empty XML formats. The fix prevents the system from attempting to process invalid XML data, ensuring reports can be saved correctly. This improves the user experience and prevents data loss.
Original PR description
Currently an error is generated when the user tries to save a report with an empty XML format. Steps to reproduce: - Install web_studio and sale_management - Sales > Studio > Reports > New > External…
Currently an error is generated when the user tries to save a report with an empty XML format. Steps to reproduce: - Install web_studio and sale_management - Sales > Studio > Reports > New > External > Type Text in report - Save > Edit Sources > Remove full XML > Save Error: `XMLSyntaxError:Document is empty, line 1, column 1 (<string>, line 1)` This error occurs because line [1] in `web_editor` attempts to access nodes by using `etree.fromstring()` with an empty `view.arch`, which is empty, resulting in an error. In earlier versions, this error was already handled by the `_check_xml` constraint, which raised a validation error when an `etree.ParseError` occurred while parsing `etree.fromstring(view.arch)` with an empty `view.arch` (see code reference [2]). However, recent changes introduced in commit [3] allow `view.arch` to be empty. As a result, this error is no longer handled by the constraint. This commit fixes the issue by adding a condition to prevent calling `etree.fromstring()` when `view.arch` is empty, avoiding attempts to access nodes from invalid data. It also updates the logic in the `web_studio` module's `get_xml_editor_resources` method to ensure resources are processed only when a valid view architecture is available. [1]: https://github.com/odoo/odoo/blob/8a88756bed194910bc5a47e93f0e29610dbeee1f/addons/web_editor/models/ir_ui_view.py#L367 [2]: https://github.com/odoo/odoo/blob/75ca0fec9a0d3b1e3a05a8bf3101bbe21846ac7a/odoo/addons/base/models/ir_ui_view.py#L372-L377 [3]: https://github.com/odoo/odoo/commit/8334ea5c777e5a478f12b8bb7a2f54bcae537d0f sentry-6288795955 Forward-Port-Of: odoo/enterprise#112111 Forward-Port-Of: odoo/enterprise#88613
This fix addresses a technical issue where AI response errors triggered 500 Internal Server Errors, impacting user experience. Now, errors are presented as messages from the AI agent, providing a smoother and more user-friendly experience for business users.
Original PR description
Currently, when an error occurs during `/ai/generate_response` calls from the frontend, a `UserError` is logged with its exception stack instead of being emitted as a logger warning. Additionally, an…
Currently, when an error occurs during `/ai/generate_response` calls from the
frontend, a `UserError` is logged with its exception stack instead of being
emitted as a logger warning. Additionally, an `UncaughtPromiseError` is
surfaced on the UI.
Error:
```
Error on request:
Traceback (most recent call last):
File "/home/odoo/src/enterprise/saas-19.1/ai/utils/llm_api_service.py", line 302, in _request
response.raise_for_status()
File "/usr/lib/python3/dist-packages/requests/models.py", line 1021, in raise_for_status
```
The issue originates from the `/ai/generate_response` route, which is
defined as a controller `type="http"` to handling POST requests. When
line [1] raises an exception inside this controller, it automatically converts
the unhandled exception into an HTTP response. As a result, the request
returns a `500 Internal Server Error`, which then propagates to the frontend
and appears as an `UncaughtPromiseError`.
This commit fixes the issue by returning internal errors as chat
messages instead of raising exceptions. As a result, the error is
displayed as a message received from the AI agent, rather than
propagating as a server error to internal users.
[1]: https://github.com/odoo/enterprise/blob/423dee8f565a6ca7cd88ec0625a5059920725f50/ai/controllers/thread.py#L83
Sentry-5691330773This update fixes an issue where tax returns were incorrectly including Italian pension fund taxes, leading to discrepancies between reports and the backend view. The change excludes these taxes from the tax return domain, ensuring accurate calculations and consistent reporting for Italian customers. This resolves a reported inconsistency.
Original PR description
The "amount to pay" incorrectly included the Pension Fund taxes, causing inconsistencies between the report and what the customer was able to see in the backend. Now we exclude them from the tax return domain. Steps to reproduce: - Create an Italian company with the Italian CoA - Install `l10n_it_edi_withholding` (not necessary in v19) - Create an invoice - Set the 4% INPS or 4% F.Pens taxes on a line, along with with a normal 22% VAT - Create a tax return Ticket [link](https://www.odoo.com/odoo/project.task/5909407) opw-5909407 Forward-Port-Of: odoo/enterprise#111311
A test used in the Odoo Enterprise payroll module failed due to an incorrect date calculation. This fix adjusted the test environment to ensure accurate results, preventing future disruptions to payroll processing. The change addresses a discrepancy in how dates were being interpreted during testing.
Original PR description
[FIX] l10n_ch_hr_payroll_elm_transmission: fix avs test for faketime build
Bug reproduction:
1 - v.17->run test_generic_avs_deductions test with faketime 2027-01-01 12:00 UTC->test fails
Bug cause:
1 - In the test, compute_sheet()->_get_payslip_lines->_compute_rule->_get_avs_rates is called
2 - There is a line like that if line.date_from <= target and (not line.date_to or target <= line.date_to)
3 - I looked to avs_line_ids = fields.One2many(default=_get_default_avs_line_ids)
4 - In _get_default_avs_line_ids -> 'date_from': fields.Date.today().replace(month=1, day=1) date_from is calculated like that -> when the year is 2027, the date_from is 2027-01-01 and it is bigger than the target in the test.
Bug solution:
1 - I used @freeze_time("2026-02-28") in my test to prevent this behavior.
Runbot Error Link: https://runbot.odoo.com/odoo/runbot.build.error/240992
task - 6018940
Forward-Port-Of: odoo/enterprise#109975This update corrects an issue where work orders weren't properly tracking consumed components. The previous changes had unintended consequences, so this revert ensures accurate tracking of materials used in work orders. A new test has also been added to prevent similar problems in the future.
Original PR description
Commit [1] has been merged with another commit OC side. However, the latter has impacted some other use cases. This is the reason why we need to revert both. The current commit also improves a test in `test_consume_component.py` to cover the case that has been broken [1] 75febe5a72f091a9940b27c7a59a31f3fe3c407a opw-5939156 Forward-Port-Of: odoo/enterprise#110675
This update fixes a previous error that caused tracebacks when users interacted with the AI using documents opened in the file viewer. The fix ensures the correct file ID is passed to the AI, resolving a 404 error and improving the AI's ability to process documents. Additionally, the AI's behavior when handling images was stabilized.
Original PR description
Before this commit, whenever a user tried to interact with the ai regarding a document opened in the file viewer, they would get a traceback with a 404 error. This was caused by the file id that we passed in the `openAIChat` method of the `AIChatLauncher` service. The id is negative on purpose by the documents team - there is a comment stating that it "prevents a reload from resolving to a real record". Also, the id doesn't reflect the attachment_id, but rather another id dedicated to the file_viewer. On the AI side, when using the id to search for the attachment to send to the AI, we get an error because the id is negative. This bubbles up to the user. We fix this by replacing the `this.file.id` with the `this.file.documentData.attachment_id.id` which is the correct value of the id associated with this document's attachment. Task-6030598
This update ensures that changes to salary information within the Odoo system only affect related calculations, specifically the mobility budget. Previously, changes in other areas could trigger unintended updates, now the system is more consistent and reliable when managing salary configurations. This improves data accuracy and reduces potential errors.
Original PR description
For consistency purposes, we only trigger the inverse on the mobility budget computation if we are in the context of the salary configurator. Changing the wage in the back end or changing the employer cost should only touch the wage and not other benefits
This update resolves a technical issue where a controller in the E-Commerce localization module (l10n_eg_iot) was incorrectly referencing outdated code from a previous Odoo version. This fix ensures the module functions correctly and avoids potential disruptions to the E-Commerce process. It's a routine maintenance update.
Original PR description
`iot_box_setup` override is still calling the previous method names, mistakenly fw ported from 19. This commit fixes it.
This update resolves a crash issue when opening tax reports in Odoo Enterprise. The fix ensures reports without a defined return type automatically use the company's tax periodicity, preventing errors and improving report stability. This enhances the reliability of financial reporting.
Original PR description
When a report uses 'previous_return_period' date_scope on one of its expressions, if there's no account.return.type linked to that report, the opening of the report crashes. This is a bit stupid,…
When a report uses 'previous_return_period' date_scope on one of its expressions, if there's no account.return.type linked to that report, the opening of the report crashes. This is a bit stupid, since a return type without periodicity will anyway fallback to the the company's tax periodicity field. When there's no return type, we should simply fallback in the same way. To reproduce: - Make a Belgian company, install the CoA and localization - Manually uninstall l10n_be_reports - Try opening the tax report Another message also checked that we couldn't compute this date_scope in case there was more than one return type linked to the report, arguing they have different periodicities, so we can't infer which one to use. However, it they actually shared the same periodicity, that check failed anyway. We refine it to authorize this case, and only raise if they truly have different periodicities. opw-6022150 Forward-Port-Of: odoo/enterprise#111872 Forward-Port-Of: odoo/enterprise#111796
This update fixes an issue where selected failure locations weren't being applied during product repairs. Now, when a quality check fails, the product is automatically moved to the user-specified failure location, ensuring accurate inventory and repair tracking. This improves the reliability of the repair process.
Original PR description
Before this commit: ------------------------- - In the Repair module, when a quality check for a product was marked as failed, Even after selecting a failure location, the failure location is not…
Before this commit: ------------------------- - In the Repair module, when a quality check for a product was marked as failed, Even after selecting a failure location, the failure location is not being set at the final product move. - Instead of showing the selected failure location, the system displayed another location as the move destination after completing the repair process. Steps to reproduce: ------------------------- 1. Install the quality_repair module. 2. In Quality, create a Control Point with: - Type = Pass-Fail - Control Per = Product or Operation - Set at least 1 Failure Location 3. Create a Repair Order for any product and start the repair process. 4. Perform a quality check, set it to Fail, and select a failure location. 5. Open the product moves, the destination location does not match the selected failure location. Cause of the issue: ------------------------- The failure location was not correctly assigned when a quality check failed during the repair process because _move_to_failure_location determines the destination location based on a stock picking (for receipts) or a production_id (for manufacturing). In the Repair module, however, quality checks are linked to a repair order, so the selected failure location was not set correctly. After this commit: ----------------------- - When a quality check fails in a repair order, the product’s destination location is correctly set to the failure location selected by the user. - This ensures that, upon completion of the repair, the product is moved to the selected failure location, maintaining accurate inventory tracking and management. Task ID:5254334 Forward-Port-Of: odoo/enterprise#99235
This update fixes an issue where users were incorrectly grouping POS orders in the l10n_pe_edi_pos module. The system now validates order groupings, preventing errors and providing clear messages to users attempting to combine invoices that don't meet the required criteria. This ensures accurate reporting and compliance for Peruvian businesses.
Original PR description
Joining the values in the selection field with a coma, and then putting everything in another selection field was plain wrong. We now check a bit better what we're generating, and refrain the user with error messages when they try grouping on the same invoices orders that do not share the necessary key values. Forward-Port-Of: odoo/enterprise#111616
This update prevents unnecessary rental planning slots from being created when the 'Plan Services' feature is disabled. Previously, updating a rental order would trigger the creation of slots, even without planning. This fix ensures that slots are only generated when 'Plan Services' is enabled, streamlining the rental planning process.
Original PR description
Steps to reproduce: ------------------- 1. Install `sale_renting_planning`. 2. Create a rental service product with: - "Can be Sold" enabled - "Plan Services" disabled - UoM set to "Units" 3. Create and confirm a rental order with this product. 4. Go to Planning and check for slots related to this order. (no slots at this stage) 5. Update the quantity of the rental order. 6. Check Planning again for slots related to this order. Issue: ------ Planning slots are created after updating the quantity of the sale order, even when "Plan Services" is not enabled. Cause: ------ Slot records are created without checking whether "Plan Services" is enabled, which leads to unwanted planning entries. related commit: 74eef70 Solution: --------- Add a condition to ensure planning slots are created only when "Plan Services" is enabled. opw-6051012 Forward-Port-Of: odoo/enterprise#112278
This update clarifies the error message displayed when an upsell's start date is set after the next invoice date. This change ensures users receive clearer guidance, preventing confusion and potential issues with subscription billing. It's a simple fix to improve the user experience.
Original PR description
Update the error message when an upsell start date is on or after the next invoice date, so it be more clear for the users. task-5893032 Forward-Port-Of: odoo/enterprise#106757
This update resolves an issue where the XML generated for Swiss payments (iso20022_ch) was using an outdated payment schema. The fix ensures the XML adheres to current Swiss banking standards, improving payment processing accuracy and compliance. It also includes enhancements for validator schema and QR-IBAN handling.
Original PR description
**PROBLEM** According to documentation (https://www.six-group.com/dam/download/banking-services/standardization/sps/ig-credit-transfer-sps-2025-en.pdf) PstlAdr must be structured. This isn't the case when generating a xml for the payment method iso20022_ch. **STEP TO REPRODUCE** 1. install l10n_ch and account_iso20022. 2. Create a swiss contact with a full address. And activate payment on the bank account of this contact. 3. Select the Company CH, and set a bank account in the bank journal configuration. 4. Create a vendor payment to the swiss contact. 5. Create a batch payment with it, and validate to get the xml. 6. Open the xml, and notice the PstlAdr isn't structured. Ticket [link](https://www.odoo.com/odoo/project.task/5880247) opw-5880247 Forward-Port-Of: odoo/enterprise#111716 Forward-Port-Of: odoo/enterprise#107025
This update fixes an issue where the canteen cost was incorrectly calculated for Belgian employees, even when they had no attendance recorded. The fix ensures that the canteen cost is only applied if the employee has earned money through attendance or work during the payslip period, preventing incorrect charges.
Original PR description
[FIX] l10n_be_payroll: fix canteen cost computation
Bug reproduction: belgium company -> create a new employee -> new contract (payroll wage > 0) -> canteen_cost = 50 -> create payslip -> allocate time off for full month (such that there will be no attendance) -> recompute payslip -> still canteen cost is calculated
Bug cause:
1 - If l10n_be_canteen_cost is > 0 it was computing the canteen cost line for sure
2 - If result_rules['BASIC']['total'] is > 0 then the canteen cost was 50.
Bug solution:
1 - I add worked_days['WORK100'].amount != 0 to the computation condition.
2 - If there is any earned money from attendance or working in that payslip duration, the canteen cost should be deducted completely
3 - If the employee is absent during the payslip, the employee should not pay the canteen cost.
task - 6045406
Forward-Port-Of: odoo/enterprise#111995
Forward-Port-Of: odoo/enterprise#110991This update resolves a bug where commission calculations were incorrectly defaulting to 0% when the target completion was set to 0%. The fix ensures that commissions are accurately calculated when the target is 0, addressing a potential revenue discrepancy. This improvement impacts sales reporting accuracy.
Original PR description
Before this commit, when target completion was 0% and the commission was equal to X (where X is not null), the commission could not be equal to X. It would be equal to 0. It was working with target amount equal to 0.
This update resolves an issue where excessively long product names in the Master Production Schedule would cause other schedule columns to disappear from view. The fix wraps long text within product names to prevent this visual disruption, ensuring all schedule information remains accessible.
Original PR description
Problem: In the master production schedule, if a product on the schedule has a name that would extend to the right edge of the screen, all of the other colums for the schedule will be completely hidden. Solution: We will wrap the text in the <a> tag containing the product name. Steps to Replicate (Runbot v19): 1. Open the Master Production Schedule 2. Click the pencil on one of the products 3. Click into the product and change its name to be something very, very long 4. Navigate back to the MPS and notice that you cannot see the actual schedule elements, even if you scroll to the end. opw-6066088 Forward-Port-Of: odoo/enterprise#111896
This update fixes an error in how project profitability costs were calculated, ensuring accurate tracking of expenses related to purchase orders. The change adjusts the accounting to correctly reflect the cost of goods, preventing double-counting and improving financial reporting. This ensures the 'To Bill' and 'Billed' amounts align with the actual purchase order cost.
Original PR description
Steps to reproduce: ----------------------------------------- 1. Install `sale_purchase_project` and Accounting modules 2. From settings, enable Budget Management 3. Create a new product with type…
Steps to reproduce: ----------------------------------------- 1. Install `sale_purchase_project` and Accounting modules 2. From settings, enable Budget Management 3. Create a new product with type Service and enable Create a project on order. 4. Create and confirm the sale order with that product (note the name of created project) 5. Create and confirm purchase order as follows: > In other information page, select the created project in the Project field > Add the same product in POL, Set price unit price to 100 and remove any tax 6. Create and post a Vendor Bill for the same vendor as the PO as follows: > Add Bill line with label downpayment > Set the Analytic Distribution to the created project > Set amount to 30 7. Go to the created purchase order > Click on bill matching 8. Select the downpayment bill > Add to PO > Select created PO > Add Down Payment 9. Go to the created project and open dashboard Observation: ----------------------------------------- In the Costs section: Expected Cost: 130 To Bill: 100 Billed: 30 Expected values: ----------------------------------------- Expected Cost: 100 To Bill: 70 Billed: 30 Issue: ---------------------------------------- In the following code: https://github.com/odoo/odoo/blob/7e81c528ae350aab4432207f5655dcfadf6ec627/addons/project_purchase/models/project_project.py#L186-L190 When an invoice line was posted (billed), the code correctly subtracted the cost from `amount_invoiced` (making it negative, representing actual cost). But the billed amount was NOT removed from `amount_to_invoice`. This caused double counting the same cost appeared in both 'To Bill' and 'Billed' Solution: ----------------------------------------- Replaced the quantity-based calculation with a proper amount-based approach: - Introduced `total_invoiced_amount` to track the sum of all non-refund invoice line amounts (both posted and draft). - Modified the unbilled calculation to: `PO_amount - total_invoiced_amount`, ensuring that the unbilled portion accurately reflects what remains to be invoiced from the purchase order. - Excluded refunds from `total_invoiced_amount` calculation because credit notes represent reversals of previous invoices, not consumption of the purchase order. Refunds still correctly affect the "billed" and "to_bill" buckets through the normal invoice line processing. This ensures the accounting principle is maintained: Total Expected Cost = Billed + To Bill = Purchase Order Amount opw-5167734 Forward-Port-Of: odoo/odoo#245649
This update resolves an issue where right-clicking while editing a message in the email system displayed the Odoo context menu instead of the standard browser menu. Now, right-clicking correctly opens the browser's default context menu, improving the user experience and consistency.
Original PR description
Before this commit, right-clicking while editing a message opened the message context menu instead of the browser's default menu. After this commit, right-clicking while editing a message opens the browser's default context menu, and the message context menu is no longer triggered. task-6065753
This update resolves an issue that prevented users from creating scrap orders when a scrap location was missing. The fix ensures the system handles the absence of a scrap location gracefully, preventing a technical error and allowing users to properly dispose of excess inventory. This improves the reliability of the stock management process.
Original PR description
When user tries to create a scrap order without scrap location, A traceback is raised. Steps to reproduce the error: - Install ``stock`` module - Go to Inventory > Configuration > Settings > Enable Storage Locations > Save - Go to Configuration > Locations > Delete Virtual Locations/Scrap > Delete - Go to Operations > Scrap > New Traceback: ```py KeyError: 1 ``` https://github.com/odoo/odoo/blob/7d89c092ac25ffe149fb38fb52863fdaa3b6ed5f/addons/stock/models/stock_scrap.py#L93 When the Scrap location is deleted, ``locations_per_company`` becomes an empty dictionary. Accessing a key from this empty dictionary lead to the above traceback. sentry-7307394327 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252192
This update fixes an issue where code blocks within toggle lists would lose their formatting when the toggle was closed. The code now correctly preserves newline characters within the code block's HTML, ensuring that multi-line code is displayed accurately regardless of the toggle's state. This improves the user experience when working with code snippets.
Original PR description
### Steps to Reproduce: - Create a toggle list and add content. - Expand the toggle list and insert a code block (e.g.: /code). - Add multiple lines inside the code block using Enter. - Refresh the…
### Steps to Reproduce: - Create a toggle list and add content. - Expand the toggle list and insert a code block (e.g.: /code). - Add multiple lines inside the code block using Enter. - Refresh the page with the toggle open, content is preserved. - Close the toggle and refresh then content collapses into one line. ### Description of the issue/feature this PR addresses: - When the toggle list is closed, the code block is inside `display: none` container. In this state, `innerText` depends on rendered layout and does not preserve newline characters `\n`. As a result, multiline code content is extracted as single line. ### Desired behavior after PR is merged: - Read html and normalize it into plain text by: - Converting `<br>` tags into newline characters. - Stripping remaining HTML tags. - Decoding HTML entities back to their literal characters. - Removing the extra newline introduced by a trailing `<br>` - Cleaning up invisible zero-width characters. task-5909034 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248391
This update ensures the HTML editor's testing process always uses the Roboto font, eliminating potential inconsistencies across different computer environments. This resolves previous test failures related to font variations and guarantees a reliable and predictable user experience for the HTML editor.
Original PR description
Purpose of this PR: - Explicitly load Roboto using FontFace in indent.test.js to avoid fallback fonts (e.g. Ubuntu) across environments. This ensures consistent rendering and prevents flaky failures caused by font-dependent computed values. task-5916115 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256070
This update resolves a bug where custom snippets using the 'Category' dynamic snippet didn't display correctly in the website preview. The fix ensures that dynamic content from this snippet is now accurately reflected in the preview, improving the user experience when creating custom website content.
Original PR description
Commit 00cf9375b356b2316e24d97234474685e3fb7f94 added the new dynamic snippet for category of product, with a specific interaction. Commit 534a42029d757935788220549aabb8914302a4f3 shows dynamic content of dynamic snippet in snippets preview dialog, but `DynamicSnippetCategory` was missed (in forward port). This commit includes the interaction to load the dynamic content of "Category" dynamic snippet in the snippets preview dialog. Steps to reproduce: - Open website builder - Add a dynamic snippet `s_dynamic_snippet_category_list` - Save the snippet as a custom snippet - Click on "Custom" snippet category - Bug: The preview for the custom snippet does not have the dynamic part task-5427353 Forward-Port-Of: odoo/odoo#255850
This update resolves an issue where prices were still visible in Sale Order subsections even when 'Hide Prices' was enabled on the parent section. The fix ensures that price information is consistently hidden across all sections, including subsections, providing a cleaner and more accurate view of sale order totals. This improves the user experience and data clarity.
Original PR description
Steps to reproduce: --- - Install `Sales` module. - Create a Sale Order. - Add a section with products. - Add a subsection under it with products. - Enable `Hide Prices` on the section. - Enable…
Steps to reproduce: --- - Install `Sales` module. - Create a Sale Order. - Add a section with products. - Add a subsection under it with products. - Enable `Hide Prices` on the section. - Enable `Hide Composition` on the subsection. - Preview the Sale Order. Issue: --- - Prices are still visible in the subsection (grouped view) even though `Hide Prices` is enabled on the parent section. Root cause: --- - The variable `show_section_total` was defined only within the main rendering block and not reused in the grouped (`t-else`) block. - The grouped section summary (used when `collapse_composition=True`) did not respect the parent section's `collapse_prices` setting, causing prices to be displayed. Solution: --- - Moved `show_section_total` definition outside the main conditional block so it can be reused in both rendering paths. - Applied `t-if="show_section_total"` to price fields in the grouped section summary to ensure consistency with the parent section's price visibility. Before: --- <img width="1030" height="232" alt="image" src="https://github.com/user-attachments/assets/1ac05e5e-6841-420f-909f-994690656cc0" /> After: --- <img width="1023" height="232" alt="image" src="https://github.com/user-attachments/assets/921ae337-4d53-433a-a42b-bdc437181889" /> opw-5979807 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255464
This update fixes an issue where the shipping weight for deliveries wasn't correctly updated when changing the pack type after using the 'put in pack' action. Previously, the system didn't account for the base weight of the new pack type, leading to inaccurate shipping calculations. This ensures accurate shipping costs are reflected in deliveries.
Original PR description
Issue ----- Doing `action_put_in_pack` then changing the pack type to one with a base weight doesn't correctly update the picking's `shipping_weight`. Steps to reproduce ----- - Enable packages - Create package types: - Big box with base weight of 5kg - Huge box with base weight of 15kg - Create a product AAA with weight of 10kg - Create a delivery for 1 unit of AAA - Confirm delivery - Put in pack - Update the pack type to "Big box" > shipping_weight is still 10kg instead of 15kg - Put in pack again - Update the pack type to "Huge box" > shipping_weight is still 10kg instead of 30kg Cause ----- Changing the package type doesn't change its' `shipping_weight`, so we don't trigger the picking's `_compute_shipping_weight`. ----- Ticket: opw-5975689 Forward-Port-Of: odoo/odoo#255764
This update replaces the old iDEAL logo with the new Wero logo for improved brand consistency. This change ensures accurate representation of the payment method and aligns with Wero's branding standards. It’s a minor update to the payment process.
Original PR description
Before the commit: The iDEAL payment method was using the existed legacy iDEAL logo. After the commit: - Updated the display name to "iDEAL / Wero". - Replaced the legacy iDEAL logo with the new Wero logo. - Introduced a separate "Wero" payment brand. task-5922938 Forward-Port-Of: odoo/odoo#254901 Forward-Port-Of: odoo/odoo#248506
This update corrects a bug where modifying a recurring event's start time caused duplicate events to be created in Outlook. The fix ensures Microsoft IDs are preserved, preventing notification issues and maintaining accurate event synchronization.
Original PR description
When an attendee syncs a recurring event where the first occurrence (base event) was modified by the organizer, `_write_from_microsoft` falsely triggers the destructive recreation path. This happens because `_has_base_event_time_fields_changed` compares the exception's modified time against the seriesMaster's pattern time, detecting a "change" even though the master hasn't changed. This causes: - All non-base events lose their microsoft_id and ms_universal_event_id - The base event gets recreated without Microsoft IDs - A duplicate event is pushed to Outlook on the next odoo2microsoft sync - Spurious "join the meeting now" notifications are sent to attendees Add a `follow_recurrence` guard so that when the base event is an exception (follow_recurrence=False), the non-destructive else branch is taken instead, preserving all Microsoft IDs. Forward-Port-Of: odoo/odoo#256263 Forward-Port-Of: odoo/odoo#254414
This update resolves an issue where users would encounter an error when attempting to save reports with empty XML formats. The fix prevents the system from attempting to process invalid XML data, ensuring reports can be saved correctly. This improves the user experience and prevents potential data corruption.
Original PR description
Currently an error is generated when the user tries to save a report with an empty XML format. Steps to reproduce: - Install web_studio and sale_management - Sales > Studio > Reports > New > External…
Currently an error is generated when the user tries to save a report with an empty XML format. Steps to reproduce: - Install web_studio and sale_management - Sales > Studio > Reports > New > External > Type Text in report - Save > Edit Sources > Remove full XML > Save Error: `XMLSyntaxError:Document is empty, line 1, column 1 (<string>, line 1)` This error occurs because line [1] in `web_editor` attempts to access nodes by using `etree.fromstring()` with an empty `view.arch`, which is empty, resulting in an error. In earlier versions, this error was already handled by the `_check_xml` constraint, which raised a validation error when an `etree.ParseError` occurred while parsing `etree.fromstring(view.arch)` with an empty `view.arch` (see code reference [2]). However, recent changes introduced in commit [3] allow `view.arch` to be empty. As a result, this error is no longer handled by the constraint. This commit fixes the issue by adding a condition to prevent calling `etree.fromstring()` when `view.arch` is empty, avoiding attempts to access nodes from invalid data. It also updates the logic in the `web_studio` module's `get_xml_editor_resources` method to ensure resources are processed only when a valid view architecture is available. [1]: https://github.com/odoo/odoo/blob/8a88756bed194910bc5a47e93f0e29610dbeee1f/addons/web_editor/models/ir_ui_view.py#L367 [2]: https://github.com/odoo/odoo/blob/75ca0fec9a0d3b1e3a05a8bf3101bbe21846ac7a/odoo/addons/base/models/ir_ui_view.py#L372-L377 [3]: https://github.com/odoo/odoo/commit/8334ea5c777e5a478f12b8bb7a2f54bcae537d0f sentry-6288795955 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256009 Forward-Port-Of: odoo/odoo#255316
This update fixes an error in the AVCO audit report that was miscalculating added value, leading to inaccurate financial reporting. The change ensures the AVCO value is correctly updated based on the last incoming movement, resolving discrepancies in reported values and improving the accuracy of inventory valuation.
Original PR description
The AVCO audit report currently recalculates the AVCO value on outgoing moves. Based on the logic in `run_average_batch()`, it should instead use the AVCO value computed on the last ingoing move to…
The AVCO audit report currently recalculates the AVCO value on outgoing moves. Based on the logic in `run_average_batch()`, it should instead use the AVCO value computed on the last ingoing move to recalculate the
`added_value`.
On the other hand, the `added_value` should not be recomputed from the AVCO value on ingoing moves.
Source of those changes: [245141](https://github.com/odoo/odoo/pull/245141)
Steps to reproduce the issue:
1. Create a new product. Do not assign it to a category yet.
2. Set the cost (standard_price) to 10$ on the product form.
3. Add 10 units to inventory.
4. Sell and deliver 5 units to a customer.
5. Purchase 10 units at 25$/ea and validate the receipt.
6. Sell and deliver 5 units to a customer.
7. Assign the product to category with AVCO cost method.
8. Go to the AVCO justification report:
- The added value on the purchase is incorrect: 200$ instead of 250$.
- On the last delivery: the added value is -125$ and the AVCO increases from 20$ to 25$.
Ticket: opw-5921104
Forward-Port-Of: odoo/odoo#252239This update ensures the 'Looking for Help' timer is always displayed for live chat channels, regardless of whether an agent is currently involved. This is crucial for accurately tracking service level agreements and ensuring timely escalation of customer inquiries. The fix also corrects inconsistencies in the mock server's timer calculations.
Original PR description
**Description of the issue this PR addresses:** Ensure the `Looking for Help` timer is shown even when the current user is already a member of the livechat channel. **Steps to Reproduce:** 1. Log in…
**Description of the issue this PR addresses:** Ensure the `Looking for Help` timer is shown even when the current user is already a member of the livechat channel. **Steps to Reproduce:** 1. Log in as a visitor and as Mitchell Admin (Live Chat operator). 2. From the visitor side, select I have a pricing question. 3. From the admin side, mark the conversation as Looking for Help. 4. The channel appears in the Looking for Help category. 5. Observe that the timer should be visible there (e.g., 1m). **Current behavior before PR:** - The timer was hidden when an agent was already a member of the conversation, assuming that once an agent joined, the `waiting for help` phase was over. - However, in escalation workflows an analyst may escalate a chat and remain a member while the channel returns to the `Looking for Help` state for another expert. In this case, the escalating analyst could not see the timer needed to track SLA requirements (e.g., creating a ticket after 10 minutes). - Also, the mock server did not recompute `livechat_looking_for_help_since_dt` when `livechat_status` changes, leading to incorrect timer values (e.g., showing 2d instead of < 1m after switching back to Looking for Help). **Desired behavior after PR is merged:** - The timer is displayed whenever the channel is in `need_help` and `livechat_looking_for_help_since_dt` is set, regardless of whether the current user is a member of the channel. - The mock server now mirrors server-side behavior by updating `livechat_looking_for_help_since_dt` when livechat_status changes, prevents missing recomputations and ensuring consistent test behavior. task-[6009851](https://www.odoo.com/odoo/project/1519/tasks/6009851) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a technical error that prevented users from sending follow-up reports by post. The fix allows the system to access the IAP account with elevated privileges, ensuring successful report generation. This resolves a previous access restriction impacting the snailmail functionality.
Original PR description
Issue: Before this commit, when sending a follow up report by post, an access error is thrown if the user doesn't have enough access to read from res.company model Fix: Access the IAP account as sudo opw-6050041 Forward-Port-Of: odoo/odoo#255431
This update corrects a visual issue in Odoo invoices where information within hidden product sections wasn't properly aligned with the surrounding text. This resulted in a slightly unprofessional appearance of downloaded invoices. The fix ensures all invoice data, including hidden sections, is presented consistently for improved clarity and a better user experience.
Original PR description
Issue: Information displayed about sections with hidden composition are not align with the other lines. Steps to reproduce: - Create an invoice - Add a product - Add a section with any product. - Hide the composition of the section (with the 3 dots on the right) - Download the invoice PDF Current behavior: - Information on the hidden section compo are not align with other lines opw-6017276 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255494
This update fixes an issue where sale order prices weren't accurately reflecting the original, undiscounted amount, especially when discounts were applied. The change ensures that the base price is calculated correctly, excluding any discount lines, leading to more reliable pricing and reporting. This improves the accuracy of sales data.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#245246
This update fixes an issue where kit products were incorrectly reporting the full sales price of each component within delivery DDTs. Previously, the report showed individual component values instead of the total kit value. This change ensures accurate reporting of kit component values, improving financial accuracy for IT companies using the system.
Original PR description
Steps to reproduce: - Have an IT company setup - Create a product with a Sales Price and define a kit BOM with 2 components - Create SO with product - Confirm, go to delivery, validate - Print Issue: In the delivery DDT, there is a summary of the delivery where each item has its own entry (product, quantity, value). However, in case of kit BOM, each component is reported with the full value of the sale operation. Analysis: This occurs because in the report code we don't consider the possibility of kit products, where multiple components are associated to the same sale line. Ticket [link](https://www.odoo.com/odoo/project.task/5013606) opw-5013606 Forward-Port-Of: odoo/odoo#255676 Forward-Port-Of: odoo/odoo#224103
This update resolves a crash that occurred when closing the AI chat window in Odoo. The issue stemmed from a misconfiguration within the system's record list management, leading to incorrect data updates. This fix ensures the AI chat window can be closed without causing a system error.
Original PR description
Before this commit, closing an AI chat window could lead to the following crash: ```js TypeError: Cannot read properties of undefined (reading '_raw') ``` Steps to reproduce: - have no chat windows…
Before this commit, closing an AI chat window could lead to the following crash: ```js TypeError: Cannot read properties of undefined (reading '_raw') ``` Steps to reproduce: - have no chat windows open, cache cleared. - open DM with demo in chat window from messaging menu, in home menu. - open AI chat, from systray. - close the AI chat window. => crash This happens because when closing the AI chat window, it deletes the AI conversation. By deleting the AI conversation, it removes the conversation from `store.menuThreads`, which is the list of conversations to display in messaging menu. Removal of this conversation in `menuThreads` is done internally through ```js const index = recordList.indexOf(record); recordList.splice(index, 1); ``` This is done that way as to reuse custom methods of `RecordList`, especially the `splice()` that is used by many methods that mutate the record list. Internal code of the custom `splice` method does `slice()`, which is used to retrieve some records without mutating the record list. In practice, these `.slice()` were accidentally mutating the list, because they invoke the `Proxy.getter` of the `RecordList`, and when the list is flagged for `computeOnNeed` / `sortOnNeed`, invoking this `Proxy.getter` would mistakenly enable the `computeInNeed` / `sortInNeed` flags and thus mutate the list, e.g. with a sort, which may change the order of items and mess up the `index` computed in `indexOf()` step. This is what happens with the chat window. The `menuThreads` looked something like this: ```js menuThread = ["thread_1", "thread_2", "thread_3"]; ``` With the removal of `thread_2`, the `.indexOf()` is `1`, but due to `.slice()` triggering the sort, the list was changed to: ```js menuThread = ["thread_2", "thread_1", "thread_3"]; ``` ... And it instead removed `thread_1` but kept `thread_2` in list. This introduce 2 problems: - `thread_1` is mistakenly removed from relation when it shouldn't - `thread_2` is kept, but since this is a local id with no actual record in store, `recordList[index]` would return `undefined` as there's no existing record matching this local id. This commit fixes the issue by improving internal code of record list methods to avoid accidental triggering of lazy re-compute and re-sort. The accidental re-compute and re-sort come from invoking non-implemented array methods on the proxy of record, such as: - `recordProxy.at()` - `recordProxy.slice()` These methods were just used meant to retrieve records from the record list, and they did so by using accessing through `recordProxy`. This approach has the benefit to look good as this is exactly the same as the external API, but it has the unintended side-effect of the re-compute / re-sort of lazy fields. Instead of using these methods, records are retrieved with: - raw access to get local ids in relation - convert local ids to raw records through raw access in `store.recordByLocalId` This approach, while uglier, has the benefit to not accidentally trigger the re-compute / re-sort. opw-5761279 Forward-Port-Of: odoo/odoo#251769
This update ensures that section behavior is consistent between sale orders and their templates. Previously, there were discrepancies in how optional sections and hidden sections were handled, leading to potential confusion. This fix standardizes the rules, improving the user experience and reducing errors when creating and managing sales orders.
Original PR description
This commit fixes inconsistencies between section behavior in sale orders and sale order templates. In sale orders: * A section cannot be marked as optional if it is hidden, and vice versa. * Moving an optional subsection into a hidden section resets its optional state. * Enabling 'hide composition' on a section resets the optional state of its subsections. These rules were not consistently enforced in sale order templates, leading to mismatched behavior. This commit aligns template logic with sale order behavior to ensure consistency across both. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The URL used to send e-invoices to the Serbian government has been updated. This update ensures that our Odoo system continues to correctly transmit e-invoices, complying with Serbian regulations. This change was necessary due to a recent update from the Serbian government.
Original PR description
**PROBLEM** The url to send e-invoice to the serbian government has changed. opw-6055622 Forward-Port-Of: odoo/odoo#256095
This update corrects a visual inconsistency in the 'muted' call action within discuss calls. The icon's background color was previously pink instead of red, which has now been standardized to match other similar buttons. This ensures a consistent and professional user experience.
Original PR description
Before this commit, when in discuss call and current user has microphone muted, the icon has light red / pink background color on muted instead of red. The color should be the same as the one from…
Before this commit, when in discuss call and current user has microphone muted, the icon has light red / pink background color on muted instead of red. The color should be the same as the one from "disconnect", but the difference comes from `btn-danger` with or without `.active` that has different shade of red for background: the `.active` version is lighter like in the mute button when active. `.active` classname is preferred to keep so that the visual is consistent for most discuss actions, including the ones without success / danger which a majority of these buttons have. However, the buttons with danger / success style are intended to preserve their color unchanged as the `.active` aspect is meant to tell whether the button is active or not and the slight change of color shade is not desirable in the context of discuss action list. This commit uses the same background color for danger / success / primary inline button. Other styles line dropdown and inline buttons without background had already the same colors, so this commit fixes the only case that was missing. Task-5436990 Before / After <img width="283" height="38" alt="Screenshot 2026-03-13 at 15 21 22" src="https://github.com/user-attachments/assets/3ebba48c-5b22-43e9-a915-e18a5531e660" /> <img width="270" height="41" alt="Screenshot 2026-03-13 at 15 21 45" src="https://github.com/user-attachments/assets/586d05a4-2a6c-48e0-89c6-bffa85a86e59" /> Forward-Port-Of: odoo/odoo#253923