Daily updates from Odoo
Monday, August 3, 2026
43 changes · saas-19.2
Enhancements to existing features
The Chilean F29 tax report has been updated to use a clearer six-column layout and calculate all report lines more efficiently in one step. This improves performance, accuracy, and usability for companies preparing Chilean tax submissions.
Original PR description
This commit optimizes the F29 report by using just one big query to compute the data for all the report lines at once. task-4329648 Forward-Port-Of: odoo/enterprise#106701
Payroll runs now avoid repeating unnecessary work when preparing payslips, making large payroll batches complete much faster. This improves processing time for HR and payroll teams, especially when handling many employees at once, without changing payroll results.
Original PR description
Backport of https://github.com/odoo/enterprise/pull/124776 without the populate blueprint.
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364 Forward-Port-Of: odoo/odoo#278633
Original PR description
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364 Forward-Port-Of: odoo/odoo#278633
Resolved issues and error corrections
The Journal Audit report could crash after changing and then removing the root report on the Generic Tax Report. This fix restores the report query correctly so accounting users can open Journal Audit without an internal server error.
Original PR description
Step To Reproduce: - Install the Accounting module. - Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report. - Set the Root Report to "Balance Sheet" and save. - Remove the…
Step To Reproduce:
- Install the Accounting module.
- Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report.
- Set the Root Report to "Balance Sheet" and save.
- Remove the Root Report and save again.
- Open Accounting -> Reporting -> Journal Audit.
Issue:
Opening the Journal Audit report raises an Internal Server Error with: psycopg2.errors.UndefinedTable: missing FROM-clause entry for table "account_move_line__move_id"
Reason:
The code that recreates the missing "account.move" join was not updated consistently with the other "_join()" usages. Without calling "._sudo()", the ORM builds the join using a filtered subquery (for example, adding the company filter), which changes the generated join alias(https://github.com/odoo/odoo/blob/saas-19.1/odoo/orm/fields_relational.py#L559). The SQL query still references the regular alias (account_move_line__move_id), causing the query to fail.
Reference PR:- https://github.com/odoo/enterprise/pull/101230
Solution:
Use "query.table._sudo()._join()" when recreating the missing "account.move" join, matching the other "_join()" usages and ensuring the expected join alias is generated.
before fix:-
`'account_move_line__move_id__2': (SQL('JOIN'), SQL('(SELECT "account_move".* FROM "account_move" WHERE "account_move"."company_id" IN %s)', (1,)), SQL('"account_move_line"."move_id" = "account_move_line__move_id__2"."id"'))`
Query : `JOIN (
SELECT
account_move.*
FROM account_move
WHERE account_move.company_id IN (1)
) AS account_move_line__move_id__2
ON account_move_line.move_id = account_move_line__move_id__2.id`
after fix:-
`'account_move_line__move_id': (SQL('JOIN'), SQL('"account_move"'), SQL('"account_move_line"."move_id" = "account_move_line__move_id"."id"'))`
Query : `JOIN account_move AS account_move_line__move_id
ON account_move_line.move_id = account_move_line__move_id.id`
opw-6425842
Forward-Port-Of: odoo/enterprise#125968German DATEV general ledger exports now show the exchange rate in the correct direction and round it to six decimal places. This improves compliance with DATEV formatting expectations and prevents overly long or misleading values in exported accounting files.
Original PR description
### Steps to Reproduce: 1. Activate l10n_de 2. Navigate to the General Ledger and export the "Datev DATA" 3. Column D, "Kurs," is incorrect ### Description of the issue/feature this PR addresses:…
### Steps to Reproduce: 1. Activate l10n_de 2. Navigate to the General Ledger and export the "Datev DATA" 3. Column D, "Kurs," is incorrect ### Description of the issue/feature this PR addresses: **Issue:** DATEV documentation states that the column for "Kurs" should be the ratio of WKZ-Umsatz : WKZ-Basisumsatz, which is Foreign : Base Currency. Additionally, all sample files show this column's values being rounded to 6 decimal places. Currently, when Odoo exports the general ledger as DATEV data, there is no rounding of decimal places and the formula does base / foreign amount, `line_amount / line_amount_currency`. **Solution:** In the `datev_export_csv.py` file, the relevant method is called `_l10n_de_datev_get_csv()`. In there, we can fix the line to round the value of `line_amount_currency / line_amount` to 6 decimal places. ### Current behavior before PR: Exporting the general ledger as DATEV data currently gives the reverse foreign currency rate and fails to round to 6 decimal places, which causes some values to be extremely long. ### Desired behavior after PR: The csv files should output the correct rate and be rounded appropriately. **Releted Documentation:** https://developer.datev.de/en/file-format/details/datev-format/format-description/booking-batch opw-6366276s Forward-Port-Of: odoo/enterprise#125097
Audit reports now use the company selected for the report when adding accounting report sections. This prevents the header from showing the user's default company address when the audit report is generated for another company.
Original PR description
When adding the accounting reports to the audit report, we browse the reports with the request's environment which is defaulting to the user's main company. As a result, the company's address displayed in the reports' header is not correct if we generate the audit report for any other company with a different address. https://github.com/odoo/enterprise/blob/aaab137897e6ad794247470e48d5ea91382577a3/account_reports/data/pdf_export_templates.xml#L85 We propose to inject the correct company in the report's environment. opw-6373956 Forward-Port-Of: odoo/enterprise#125125
This fixes a crash that stopped employees without Sales access from using the attendance time clock. Those users can now check in normally, while sales-only billing information is handled only when the user has the right permissions.
Original PR description
## Current behavior: When users without Sales rights open the attendance systray (the green dot icon) to check-in, the system will crash with error `TypeError: Cannot read properties of undefined (reading 'relatedPropertyField')` ## Expected behavior: Users without Sales rights should still be able to log time without any problems ## Steps to reproduce: 1. In Users setting > Access Rights tab > Sales section, give your own account any rights to access (e.g. Own Documents), observe that your account can log time via green dot icon. 2. Now try to set the Sales rights to 'No', then log time by clicking on the green dot icon to check-in. Oops! ## Cause of the issue: For users without sales access, is_billable was not returned by fields_get (group-restricted), but it still ended up in record.data ## Fix: Ensure user has the salesman rights before assigning is_billable to record data opw-6323881
This fix makes the Swedish Point of Sale test consistently complete order creation at the end of its automated flow. It reduces random test failures, helping maintain confidence in Swedish POS localization quality without changing user-facing behavior.
Original PR description
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing:…
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing: https://github.com/odoo/enterprise/blob/0f6f6fac892bc8cec477160a790d52fbf053be99/l10n_se_pos/tests/test_se_pos.py#L40-L42 ## Steps to reproduce 1. Install `l10n_se_pos` 2. Run the test `test_l10n_se_pos_01` 3. **The test fails non-deterministically** ## Fix We use `clickNextOrder()` at the end of the tour to ensure the creation of the order, like other tests already do (e.g., [FinishResidualOrder](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L676-L677), [test_name_preset_skip_screen](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L1333-L1334), [PosOrderCreationTourPdis](https://github.com/odoo/enterprise/blob/08d5172a8c3310af0c51e18a281c544f83f5aed7/pos_enterprise/static/tests/tours/point_of_sale/pos_tour.js#L141-L142), ...). runbot-238568 Forward-Port-Of: odoo/enterprise#125672
Users can now click directly into custom fields added to the Documents list view and edit them inline. This removes an extra workaround step and makes customized document workflows behave consistently with standard fields.
Original PR description
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The…
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The user has to first click a standard editable field (like "Owner") to put the row into edit mode before they can modify the custom field. This occurs because we use a hardcoded whitelist (`editableColumns`) of standard fields allowed to trigger edit mode. Custom fields (`x_`) are missing from this static list. This commit resolves the issue by dynamically injecting visible, non-readonly custom fields into the `editableColumns` whitelist. This allows user-created fields to be edited inline as expected. **Steps to reproduce:** - Documents > Studio > List view > Add any field that accepts user input (e.g. Text/char) > save/exit - In the same Documents list view > select a row > click the cell belonging to the newly created field > observe that the row does not enter edit mode - In the same Documents list view > select a row > click a standard editable cell, then click the cell belonging to our newly created field > observe that this then allows us to edit our field **Current behavior before PR:** - Custom fields do not trigger inline edit mode **Desired behavior after PR is merged:** - Custom fields trigger inline edit mode opw-6378102 Forward-Port-Of: odoo/enterprise#125378 Forward-Port-Of: odoo/enterprise#125239
This fix makes an automated barcode workflow test wait until a transfer is clearly ready to validate before pressing the validate button. It reduces random test failures, helping keep the stock barcode feature stable and release checks more dependable.
Original PR description
Make sure the validate button has the 'primary-btn' class as it means that the transfer is valid before clicking on it. runbot-939917 Forward-Port-Of: odoo/enterprise#125221 Forward-Port-Of: odoo/enterprise#125005
Swiss payroll calculations now round amounts directly to the required 0.05 precision instead of relying on a workaround that could create tiny, incorrect differences. This improves consistency in payroll declarations and helps avoid unnecessary salary-change entries caused only by rounding noise.
Original PR description
In multiple places within l10n_ch_hr_payroll_elm we use float_round to a precision of 0.01 but then manually round to 0.05 precision. 1. Open a python terminal 2. Enter 1000 % 0.05 >= 0.025 3. See this results to true, even though it shouldn't Fix this by using float_round with a precision of 0.05 instead. https://github.com/odoo/enterprise/blob/7f9cd01ff3dd470b06ae176982fd042243be8f3c/l10n_ch_hr_payroll_elm/models/hr_payslip.py#L102-L105 The change to `ema_declaration.json` is needed as previously it was expected that there was a small difference between salary over the months due to the odd rounding (a difference of like 0.000000000001). Adding the new rounding makes the values equal and test_ema_declaration_2023_01 would fail due to changeSalary no longer being in the computed dict. All the way to master! opw-6322937 Forward-Port-Of: odoo/enterprise#121401
Internal CRM users who are not administrators can once again use the business card lead generation option when the related app is available. The change fixes an overly restrictive access check while keeping administrator-only installation and proper access messages where specific permissions are required.
Original PR description
**Steps to reproduce:** - Go to CRM app as an internal user (non-admin) - Click on Generate button - Can't create leads from business card pictures - Only setting the user as admin enables it (was…
**Steps to reproduce:** - Go to CRM app as an internal user (non-admin) - Click on Generate button - Can't create leads from business card pictures - Only setting the user as admin enables it (was working fine in previous versions) **Issue:** Dropdown action is restricted to admin only by default using `hasAccess`. If there is a corresponding model on the `LeadGenerationDropdown` it is later changed according to the current user access rights using `await user.checkAccessRight(model, "create")`. **Fix:** Default `hasAccess` to `True` as there is no related model for the lead generation of business cards. (Note: could also provide the missing model ?) - Installation should be restricted to the admin. - Access message should be shown to the user if he doesn't have enough rights to the related model. - Non-admin users should be able to use the feature if no model is provided and the related app is available. dropdown: https://github.com/odoo/odoo/commit/978019522746ccb971eeb15c5d9530e438b7d2f3 business card: https://github.com/odoo/enterprise/commit/48a9cba24cb51b11a08dd9c0ff1291e15232260f opw-6258689
Activity Watch can now identify the related task directly from a configured pattern in the window title or URL. This reduces incorrect timesheet suggestions when task references are already present in activity data.
Original PR description
Before this commit, when the task_id to link to activity watch can be found in the URL or window/tab name but it is not possible for the user to create a regex to be able to automatically say to the system the task_id is found in the event name recorded by activity watch. This commit adds the possibility to define `task_id` group name inside the regex to be able to take that information instead of searching which task is linked to that event based on previous key event or the frequency of the current user. task-[6384029](https://www.odoo.com/odoo/project.task/6384029)
This fix prevents a live Argentina ARCA currency-rate test from running in daily builds where internet access is blocked. It keeps the test available for nightly runs, reducing false build failures without changing customer-facing behavior.
Original PR description
Description of the issue this commit addresses: The live ARCA currency rate test keeps the inherited `standard` tag. It is therefore selected by daily builds whose HTTP guard blocks the request. The guard also blocks it when selected by the external localization suite. --- Desired behavior after this commit is merged: This commit removes the `standard` tag from the live ARCA test. Daily builds skip the test while nightlies still run it with HTTP access. --- runbot-[238857](https://runbot.odoo.com/odoo/error/238857)
Calendar events marked as available are no longer shown as Timesheet Assistant suggestions. This keeps recommendations focused on events that may actually need timesheet entries and reduces clutter for users.
Original PR description
## Previous Behavior In the Timesheet Assistant view, calendar events marked as *available* were still being suggested. These events are not intended to be timesheeted and should not appear in the assistant’s recommendations. Their presence could also obscure more relevant events that require user attention. ## New Expected Behavior Calendar events marked as *available* are now excluded from Timesheet Assistant suggestions. task-[6431591](https://www.odoo.com/odoo/project/4105/tasks/6431591) Forward-Port-Of: odoo/enterprise#126183
This fix updates how Peruvian electronic invoices format address details so they match SUNAT's current requirements. It helps invoices pass validation by correctly handling districts and urban subdivisions under the newer standard.
Original PR description
Update electronic invoicing address nodes to align with current SUNAT requirements. This transitions the geographic data formatting from the legacy UBL 2.0 schema to the standard UBL 2.1 specification, ensuring proper structural validation for districts and urban subdivisions. Documentation used: https://cpe.sunat.gob.pe/sites/default/files/inline-files/guia+xml+factura+version+2-1+1+0+(2)_0+(2).pdf opw-6282314 Forward-Port-Of: odoo/enterprise#125406 Forward-Port-Of: odoo/enterprise#121390
Rental orders using a custom make-to-order buying route now correctly create the expected return transfer as well as the delivery and purchase. This prevents missing return operations and helps teams track rented products reliably through the full rental cycle.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental order for 1 x P and set the the MTO route on the sol - Confirm the order #### > The delivery as well as the purchase for 1 unit of P was generated but the return was not. ### Cause of the issue: The procurement generated to handle both the delivery and the return rental picking are handled by the `_create_procurements`: https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/sale_stock_renting/models/sale_order_line.py#L353-L374 The `route_ids` set and used is the `mto_route` set on the sol: https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L415-L422 https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L282-L297 However, in the present case, the mto route does not contain any rule with a relevant `location_src_id` in the rental location so that the return will not be generated. opw-6361322 Forward-Port-Of: odoo/enterprise#126078 Forward-Port-Of: odoo/enterprise#124097
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages' in the settings - Create a tracked product with package - Put 10 units in stock in package `P`. - Create and confirm a sale for 5 units - Open the delivery, make sure the quantity is set to 0 - Click 'Details' - "Add a line" and select the package P -> if you try to select a destination p
Original PR description
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages'…
**Issue** The package of the selected quant is not proposed as a destination package when adding stock move lines manually before the move line is saved. **Steps to reproduce** - Activate 'Packages' in the settings - Create a tracked product with package - Put 10 units in stock in package `P`. - Create and confirm a sale for 5 units - Open the delivery, make sure the quantity is set to 0 - Click 'Details' - "Add a line" and select the package P -> if you try to select a destination package, the package P is not proposed as it should - save it and reopen 'Details' -> if you try to select a destination package, the package P is now proposed **Cause** The domain of `result_package_id` (destination package) correctly includes `package_id`: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L52-L56 However, before saving, `package_id` is not yet populated into the new `stock.move.line` record. It will only be copied from `quant_id` by `_copy_quant_info()`: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L1016-L1025 which will only be called in the create method, while saving: https://github.com/odoo/odoo/blob/3a5f7431effd4b2b2eb8ce3eed81aaba42fcd8ea/addons/stock/models/stock_move_line.py#L350 opw-6370159 Forward-Port-Of: odoo/odoo#277797
Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never fol
Original PR description
Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never follows the server counter again. This commit freezes that state only while something is still unread locally. This also fixes the flaky test "no unread message banner after message is deleted". https://runbot.odoo.com/odoo/error/242776 Forward-Port-Of: odoo/odoo#279601 Forward-Port-Of: odoo/odoo#279195
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill Error from the portal: `[372] Invalid or Blank Consignee Ship-to State Code` It is currently a flaw in the government portal because in Government portal there is no option for the Other country (99) for Ship to state code and only option for Other Teritory(97) It is because in reality, i
Original PR description
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill…
Steps to reproduce: Use the real testing credentials Make sure the invoice sequence is not generated on the real testing credentials 1. Create an invoice with overseas partner 2. Create ewaybill Error from the portal: `[372] Invalid or Blank Consignee Ship-to State Code` It is currently a flaw in the government portal because in Government portal there is no option for the Other country (99) for Ship to state code and only option for Other Teritory(97) It is because in reality, it should the port ship to state code but there cases where goods can be transfered to nearby country i.e. Bangladesh, Nepal where good can taken by road from India In that case the state code should be 97 task-6431082 **Second Commit** - [FIX] l10n_in_ewaybill: import/export GSTIN should be URP Steps to reproduce: Use the real testing credentials Create a SEZ partner Create an invoice and ewaybill Select the type of Ewaybill as Export Tax Invoice We get error code-450 which clearly states, `450 For outward-export ewaybill, To GSTIN has to be either URP or SEZ` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279289
Currently, when using the quick create form to create a calendar.event, if you set up the event for the whole day the show_as field will always be saved as free no matter the value set by the user. Steps to reproduce: ------------------- * Open Calendar app * Select the a slot that corresponds to a whole day * Ensure all day is ticked * Change 'Available' to 'Busy' * Save * Select the slot and select Edit > Observe that the status is showing 'Available' Why the fix: ------------
Original PR description
Currently, when using the quick create form to create a calendar.event, if you set up the event for the whole day the show_as field will always be saved as free no matter the value set by the user.…
Currently, when using the quick create form to create a calendar.event, if you set up the event for the whole day the show_as field will always be saved as free no matter the value set by the user. Steps to reproduce: ------------------- * Open Calendar app * Select the a slot that corresponds to a whole day * Ensure all day is ticked * Change 'Available' to 'Busy' * Save * Select the slot and select Edit > Observe that the status is showing 'Available' Why the fix: ------------ The defaults should be: all day = free, not all day = busy However those values should still remain modifyable. This commit https://github.com/odoo/odoo/commit/62ecdba6dc963ddcdfca9e2e924ae5f6ca34e5de states: > When the user toggles allDay within the edit form, the availability is recomputed (this behavior matches google calendar) For the normal form itself the onchange triggers and behaves as stated. And if the user decides to change the show_as value it will save its choice correctly. For the quick create form, the onchange also triggers correcly. Meaning the velue of show_as is recomputed depending on allday. However upon saving, the value of show_as is bypassed if allday is true but it should keep the value selected by the user. opw-6326575
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://gith
Original PR description
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g.,…
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://github.com/odoo/odoo/blob/c1acf61ab23f231e416354a3504cc3c18170af2c/addons/hr_holidays/static/src/components/float_time_selection/float_time_selection.js#L45-L56 Here, the code attempts to parse the hours and minutes by splitting the already localized formatted string (super.formattedValue) and checking if the formatted value ended with "h" or "m". In Dutch, the localized string ends with "u" instead of "h", causing the string-matching logic to fail silently and default back to 0 (12 a.m.). Example: If we change the value to 10:30 AM, in Dutch the formatted value becomes "10u 30m". Reference: e80750d Solution: --------- Stop parsing the localized formatted string and instead compute hours and minutes directly from the float value stored in the record using `floatToHoursMinutes`, making the formatting independent of translations. opw-6303884 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: ---
Original PR description
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277748 Forward-Port-Of: odoo/odoo#277180
When a format is applied on an unsplittable node, removing it from a wider selection does not dare to touch that format to ensure it won't be split. Because of this, it becomes impossible to remove the format on such nodes. This commit slightly adapts the logic by so that instead of stopping when encountering an unsplittable node, it keeps looking higher in the hierarchy where the format is actually defined. Steps to reproduce: - Go to a "To do" note - Select a word - Apply a style (un
Original PR description
When a format is applied on an unsplittable node, removing it from a wider selection does not dare to touch that format to ensure it won't be split. Because of this, it becomes impossible to remove the format on such nodes. This commit slightly adapts the logic by so that instead of stopping when encountering an unsplittable node, it keeps looking higher in the hierarchy where the format is actually defined. Steps to reproduce: - Go to a "To do" note - Select a word - Apply a style (underscore, strikethrough...) - Type "odoo.com" - Press space to turn it into a link - Select the whole line - Try to remove the style => The style was not removed from the link. task-6322596 Forward-Port-Of: odoo/odoo#279511 Forward-Port-Of: odoo/odoo#273922
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#278201 Forward-Port-Of: odoo/odoo#271364
Original PR description
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#278201 Forward-Port-Of: odoo/odoo#271364
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`. When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)` Because `email_to` is `False` for internal p
Original PR description
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is…
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`.
When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)`
Because `email_to` is `False` for internal partners, `('outgoing_email_to', '=', False)` evaluated to `True` against the first recipient's message record. Consequently, the search falsely determined that the second recipient was already notified, suppressing OOO replies for all subsequent contacts across the 4-day window.
## Proposed solution:
We resolve this by dynamically constructing recipient sub-domains conditionally depending if `recipient` or `email_to` are set.
We also extend `test_routing_with_out_of_office` with a corresponding test case.
## How to reproduce:
1. Set up a DB with at least 3 users (User A, User B, User C).
2. Configure User A to be out of office (in user preferences)
3. Go to any chatter/mail.thread while logged as User B and tag User A in a log note. -> triggers OOO message
4. Log as User C, tag User A in a log note. -> BUG: no OOO message because the "4 day" check falsely believes that User C already received a OOO from User A
OPW-6110300
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277880Step to reproduce: 1.Go to Website ->Edit Mode 2,Add the snippet : 'AI Live Chat' 3.Don't update any Settings -> Hit 'Save' directly ( Don't add any API key for the chatgpt and/or gemini) 4.Search for something 5.Traceback occurs Before this commit: `RedirectWarningDialog` always displayed the redirect button and expected the `action` service to be available. When a `RedirectWarning` was raised from the website, where this service is not provided, the dialog crashed with an OWL error in
Original PR description
Step to reproduce: 1.Go to Website ->Edit Mode 2,Add the snippet : 'AI Live Chat' 3.Don't update any Settings -> Hit 'Save' directly ( Don't add any API key for the chatgpt and/or gemini) 4.Search for something 5.Traceback occurs Before this commit: `RedirectWarningDialog` always displayed the redirect button and expected the `action` service to be available. When a `RedirectWarning` was raised from the website, where this service is not provided, the dialog crashed with an OWL error instead of being displayed. After this commit: the redirect button is only rendered when the `action` service is available, preventing the crash on the website while keeping the existing behavior in the backend. task-6220145 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Steps to reproduce: - Install `sale_mrp` and `l10n_ke_edi_oscu_stock` - Set company country to be 'Kenya' - Run the `test_kit_cogs_entry_with_delivery_line_removal` test > odoo.exceptions.UserError: Cannot create an invoice. No items are available to invoice. ### Cause of Issue: The test validates COGS entries for a kit by creating a sale order, then generating an invoice. When `l10n_ke_edi_oscu_stock` is installed, it overrides the `invoice_policy` of all storable products for Ke
Original PR description
### Steps to reproduce: - Install `sale_mrp` and `l10n_ke_edi_oscu_stock` - Set company country to be 'Kenya' - Run the `test_kit_cogs_entry_with_delivery_line_removal` test >…
### Steps to reproduce: - Install `sale_mrp` and `l10n_ke_edi_oscu_stock` - Set company country to be 'Kenya' - Run the `test_kit_cogs_entry_with_delivery_line_removal` test > odoo.exceptions.UserError: Cannot create an invoice. No items are available to invoice. ### Cause of Issue: The test validates COGS entries for a kit by creating a sale order, then generating an invoice. When `l10n_ke_edi_oscu_stock` is installed, it overrides the `invoice_policy` of all storable products for Kenyan companies to `'delivery'`. https://github.com/odoo/enterprise/blob/82b736a283ed5ab3ad431a1cdbcedc1b8e3c2d7c/l10n_ke_edi_oscu_stock/models/product.py#L16-L21 Because the test removes a required component from the picking, the delivered quantity of the kit is computed as 0. Since the kit's invoice policy is dynamically forced to `'delivery'` by the localization, calling `_create_invoices()` raises a `UserError` as there are no delivered items to invoice, failing the test on runbot. ### Fix: Ensure that kit product use an invoicing policy of 'Ordered Quantities' rather than the default 'Delivered Quantities'. This allows the test to proceed and correctly evaluate the core COGS computation logic it was designed to check. runbot-243342
Steps to produce: --- - Install the Sales module. - Enable `Pricelists` from Sales settings. - Create a new product. - Go to Sales > Products > Pricelists and open an existing pricelist. - Add the following rules for a product: - min qty: 1 > price: 100 - min qty:10 > price: 80 - Create a new quotation > add section > add the same product. - Set the section as optional > Preview the quotation. - Change its quantity to 10. Added test covering the fix introduced in [com
Original PR description
Steps to produce:
---
- Install the Sales module.
- Enable `Pricelists` from Sales settings.
- Create a new product.
- Go to Sales > Products > Pricelists and open an existing pricelist.
- Add the following rules for a product:
- min qty: 1 > price: 100
- min qty:10 > price: 80
- Create a new quotation > add section > add the same product.
- Set the section as optional > Preview the quotation.
- Change its quantity to 10.
Added test covering the fix introduced in [commit], ensuring
that pricelist rules are correctly reapplied when the quantity of an
optional product is changed from the quotation preview.
[commit]: https://github.com/odoo/odoo/commit/93b6bdd6a4909bc0b45b90ab6a2d0734a218292d
opw-6241183
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279135
Forward-Port-Of: odoo/odoo#266597The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with n
Original PR description
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry…
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with no socket, no listeners and no pending timeout: it never reconnects. Schedule the reconnection when handling a manually triggered close, since no error event will follow to do it. [1]: https://github.com/odoo/odoo/pull/278075 runbot-944578 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279046 Forward-Port-Of: odoo/odoo#278779
to reproduce: ============= - Have a database with a large number of kit BoMs (e.g. ~160k phantom mrp.bom records). - Open Inventory Valuation. - The request never returns and hangs forever. problem: ======== Commit 11e9c1297439 started searching the valued products with `('qty_available', '!=', 0)`. On `product.product` this triggers the mrp override `_search_qty_available_new`, which loads every phantom BoM in the database and computes `qty_available` (via BoM explode) for each
Original PR description
to reproduce: ============= - Have a database with a large number of kit BoMs (e.g. ~160k phantom mrp.bom records). - Open Inventory Valuation. - The request never returns and hangs forever. problem:…
to reproduce:
=============
- Have a database with a large number of kit BoMs (e.g. ~160k phantom
mrp.bom records).
- Open Inventory Valuation.
- The request never returns and hangs forever.
problem:
========
Commit 11e9c1297439 started searching the valued products with
`('qty_available', '!=', 0)`. On `product.product` this triggers the mrp
override `_search_qty_available_new`, which loads every phantom BoM in the
database and computes `qty_available` (via BoM explode) for each kit. On top
of that, the override builds the kit products recordset with repeated
`kit_products |= ...` unions, which is O(n^2). With a large catalog of kits
the combination of O(n) heavy explodes and O(n^2) unions never returns.
On top of the performance issue, the new search dropped the kit exclusion
that `_get_accounts_by_product` previously applied through
`_get_valuation_product_domain` (`('is_kits', '=', False)` in mrp_account),
so phantom products - which are never valued on their own - were wrongly
pulled into the valuation.
solution:
=========
Restore the kit exclusion: search the valued products through
`_get_valuation_product_domain()` (which adds `('is_kits', '=', False)` in
mrp_account) instead of the ad-hoc `('is_storable', '=', True)` domain, so
phantom products are no longer valued.
Add a `skip_kit_qty_available` context key on `_search_qty_available_new` so
callers that intentionally exclude kits can skip the costly kit BoM expansion
and return the base (quant-based) result directly. The key is set in
mrp_account (via `_get_valuation_product_context`), alongside the domain that
already excludes kits, so the optimization and its precondition stay in the
same layer.
Also make the remaining kit path in `_search_qty_available_new` scale: build
the kit products recordset in a single pass instead of O(n^2) recordset
unions, and use a set for membership checks.
Benchmark:
==========
for `_get_report_data()` (averaged over 5 runs):
| # Input data (phantom kits) | Before PR | After PR |
| :---: | :---: | :---: |
| 1,000 | 2.558 s | 35.5 ms |
| 5,000 | 10.991 s | 41.6 ms |
| 10,000 | 20.869 s | 66.0 ms |
| 25,000 | 61.807 s | 80.7 ms |
| 50,000 | 195.382 s | 87.9 ms |
the improvement is **~99% faster**
opw-6312168
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273982When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2
Original PR description
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through…
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2 USD (= 80 ZIG) was correctly shown as 80 ZIG on its own, yet appeared as 2 ZIG once it was part of a combo, since the raw amount was displayed as-is in the PoS currency. Convert `base_price` and `extra_price` from each record's own `currency_id` to the PoS currency at load time, mirroring what is already done for product prices. Steps to reproduce: - Set a product to 2 USD and a PoS to a ZIG pricelist (rate 40). - Open the PoS: the standalone product shows 80 ZIG. - Add the same product as a combo item: it shows 2 ZIG instead of 80 ZIG. opw-6410243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279253 Forward-Port-Of: odoo/odoo#278330
Issue: --- `code` is hidden in `payment.method` from without dev mode, which cause an validation error when creating a new payment method. opw-6390285 Forward-Port-Of: odoo/odoo#278671
Original PR description
Issue: --- `code` is hidden in `payment.method` from without dev mode, which cause an validation error when creating a new payment method. opw-6390285 Forward-Port-Of: odoo/odoo#278671
When an order from a closed session is invoiced, a misc reversal move is created to "extract" the order from the session closing entry. When the PoS config uses a currency different from the company currency, posting that reversal move could fail with "The entry is not balanced.", making it impossible to invoice the order. Steps to reproduce: - company in currency A, PoS config in currency B, with a conversion rate producing rounding drift (e.g. 0.4007) - sell a product of 20.0 B + 15% t
Original PR description
When an order from a closed session is invoiced, a misc reversal move is created to "extract" the order from the session closing entry. When the PoS config uses a currency different from the company…
When an order from a closed session is invoiced, a misc reversal move is created to "extract" the order from the session closing entry. When the PoS config uses a currency different from the company currency, posting that reversal move could fail with "The entry is not balanced.", making it impossible to invoice the order. Steps to reproduce: - company in currency A, PoS config in currency B, with a conversion rate producing rounding drift (e.g. 0.4007) - sell a product of 20.0 B + 15% tax (23.0 B), paid by bank, without invoicing - close the session - set a partner on the order and invoice it => UserError: "The entry is not balanced." Cause: in `_prepare_aml_values_list_per_nature`, the product and tax lines each get their balance converted and rounded individually (20.0 * 0.4007 -> 8.01, 3.0 * 0.4007 -> 1.20), while the payment term line was converted from the payment total, without rounding (23.0 * 0.4007 -> 9.2161). Per-line rounding does not distribute over the sum, so the balances could differ by a few cents (8.01 + 1.20 != 9.22) and the move could not be posted. The closing entry has the balancing-account wizard as an escape valve for such differences; the reversal move had none. Fix, following what is done for regular invoices (see `account.move._compute_needed_terms`, where the payment term balance is derived from the sum of the already rounded lines): - round the payment term conversions - put the conversion residual on the last payment term line so the payment terms exactly counterbalance the other lines, but only when the amounts in currency are balanced, so it can only absorb rounding drift - include the cash rounding amounts in the accumulated totals - fix the swapped `amount_currency`/`balance` values when merging two non-split payments on the same receivable account opw-6375309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275673
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal instead of the correct one (Vendor Bills), even though the move_type itself was correct. ### Steps to reproduce the issue: Pre steps: you need to have access to https://iap-services-test.odoo.com/odoo 1. Download Accounting and l10n_it 2. Go to Settings > Companies and set the VAT of IT company
Original PR description
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal…
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal instead of the correct one (Vendor Bills), even though the move_type itself was correct. ### Steps to reproduce the issue: Pre steps: you need to have access to https://iap-services-test.odoo.com/odoo 1. Download Accounting and l10n_it 2. Go to Settings > Companies and set the VAT of IT company the same as the one in the xml 3. Go to Settings > Italian Electronic Invoicing and select Test 4. Go into the code and insert an Exception inside the function _l10n_it_edi_import_invoice after self.move_type = move_type (or create any type of exception from the user interface) 5. Go to IAP service into IT EDI app and see that your company is there as user 6. Click into the record > receive move button > upload your xml > create 7. Go to your DB > Scheduled Actions > filter with IT > IT EDI: Receive invoices from the SdI > Run Manually 8. Go to Journal entries, remove the filter and find your imported bill 9. You can see it was inserted into the Miscellaneous Operations Journal instead of a Vendor Bill Journal ### Cause of the issue: The move is created inside a savepoint context manager, designed so that even if parsing fails, an empty move with the attachment still remains. The problem is that if the exception is raised, the savepoint rollback undoes everything that follows, but the journal was already determined before the correct move_type was known, leaving the move in the wrong default journal. ### Reason to introduce the fix: The fix is needed to ensure that, regardless of where parsing fails, the move's journal is correctly set even if an exception occurs so that it is possible to find the move in the correct section even if not imported correctly. opw-6397712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279566 Forward-Port-Of: odoo/odoo#278111
Steps to reproduce the bug: - Install point_of_sale - Open the POS frontend and create a new product from the register - Add it to the order, then open its product info popup and edit it - Rename it and change its price - Confirm the edit dialog - Click on the (renamed) product again to add it to the order Problem: On runbot the tour test_product_create_update_from_frontend (point_of_sale/tests/test_frontend.py, MobileTestUi) intermittently times out waiting for the orderline to sh
Original PR description
Steps to reproduce the bug: - Install point_of_sale - Open the POS frontend and create a new product from the register - Add it to the order, then open its product info popup and edit it - Rename it…
Steps to reproduce the bug:
- Install point_of_sale
- Open the POS frontend and create a new product from the register
- Add it to the order, then open its product info popup and edit it
- Rename it and change its price
- Confirm the edit dialog
- Click on the (renamed) product again to add it to the order
Problem:
On runbot the tour test_product_create_update_from_frontend (point_of_sale/tests/test_frontend.py, MobileTestUi) intermittently times out waiting for the orderline to show the edited product name/quantity/ price combination.
editProduct()'s onSave callback in pos_store.js closed the edit dialog via act_window_close right after firing this.data.read("product.template", ...) and this.data.searchRead("product.product", ...), without waiting for either call to resolve. When the dialog closes before those RPCs land, the in-memory product record used by canBeMergedWith() (pos_order_line.js) to decide how to merge/create the next orderline can still hold the stale price, so re-clicking the product right after editing produces an orderline that never matches the expected quantity/price.
Solution:
Make onSave async and await both this.data.read() and this.data.searchRead() before closing the dialog, so the reactive store is guaranteed to hold the updated product data before the user (or the tour) can interact with the product again.
runbot-223630
Forward-Port-Of: odoo/odoo#279496
Forward-Port-Of: odoo/odoo#277698added tags for accounts and new demo data for l10n_cl_reports f29 refactor refactor file to company_demo.xml Add widthholding tax 2nd category for 2027 and 2028 since it is suitable for this report compatibility [FIX] l10n_cl: add more taxes and fix translation [FIX] l10n_cl: adapt fiscal position to new scheme. [FIX] l10n_cl: remove unused tags [FIX] l10n_cl: add fiscal position to taxes and replacement tax. Change refs in demo and fix demo values to make more consistent with real cases
Original PR description
added tags for accounts and new demo data for l10n_cl_reports f29 refactor refactor file to company_demo.xml Add widthholding tax 2nd category for 2027 and 2028 since it is suitable for this report compatibility [FIX] l10n_cl: add more taxes and fix translation [FIX] l10n_cl: adapt fiscal position to new scheme. [FIX] l10n_cl: remove unused tags [FIX] l10n_cl: add fiscal position to taxes and replacement tax. Change refs in demo and fix demo values to make more consistent with real cases [FIX] l10n_cl: change monthy taxes payable 210760 from payable to current [FIX] l10n_cl: add new ILA accounts to COA and fix ILA tax repartition lines Compatibility with 'remove tax_tag_invert' [FIX] l10n_cl: fix 'compras de combustibles' task-4329648 Forward-Port-Of: odoo/odoo#247545
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment should be enabled from the settings to proceed) 3. Once the transaction is processed and the order confirmed, check the confirmation email/PDF sent to the customer in the chatter **Issue:** - The order confirmation sent to the customer after paying online does not include the signature they provide
Original PR description
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment…
**Steps to reproduce:** 1. Create a new SO and enable "Online Signature" and "Online Payment" in the "Other Info" tab 2. Click on Preview and click on "Sign & Pay" from the portal (demo payment should be enabled from the settings to proceed) 3. Once the transaction is processed and the order confirmed, check the confirmation email/PDF sent to the customer in the chatter **Issue:** - The order confirmation sent to the customer after paying online does not include the signature they provided when accepting the quotation - Even if "Online Payment" is not enabled and Signing will directly confirm the order, the signature is still missing. **Why this happens:** - The signature block in `sale.report_saleorder_document` is gated by the `sale_include_signature` context key rather than solely by doc.signature. This was introduced by commit ef8246a4daf6146da2ed3cb78c37c7bf0937a4df to retain signature integrity. - `portal_quote_accept` only sets this context right after the customer signs on the pdf rendered for us (company), and was not passed through `_validate_order()` when there was no online payment - When online payment is required, `_has_to_be_paid()` defers the order confirmation which happens later, and the context is never set elsewhere **Fix:** - Pass the context when online payment is not required - If online payment is required, the sale quotation can be modified after being signed. However, since the customer previews the quotation when Paying, we can say the signature integrity is retained opw-6389733 Forward-Port-Of: odoo/odoo#278854
**PROBLEM** When creating a Credit Note from a Sale Order, the credit note lines uses the default account instead of using the return account set on the company. **STEP TO REPRODUCE** 1. Create a SO with a product. 2. Create an invoice and confirm it. 3. Return to the SO, and reduce the product qty (product invoice policy should be ordered qty for these steps). 4. Click again on create Invoice to create a Credit Note for the SO. 5. Notice the account on the product line is not the retur
Original PR description
**PROBLEM** When creating a Credit Note from a Sale Order, the credit note lines uses the default account instead of using the return account set on the company. **STEP TO REPRODUCE** 1. Create a SO with a product. 2. Create an invoice and confirm it. 3. Return to the SO, and reduce the product qty (product invoice policy should be ordered qty for these steps). 4. Click again on create Invoice to create a Credit Note for the SO. 5. Notice the account on the product line is not the return account. **CAUSE** In `_create_invoices()` on the SO model, we first create the moves as invoice, and then switch them to credit note if the total is negative. This means the lines are created with the invoice default account. opw-6266882 Forward-Port-Of: odoo/odoo#274354
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating th
Original PR description
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating the product name, we should first check that it would not result in an empty description picking. opw-6318785 Forward-Port-Of: odoo/odoo#275248
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037This update resolves an issue where the 'Contact Us' button on product pages wasn't correctly redirecting to snippets, specifically when a zero-price product was involved. The fix ensures that the button functions as intended, directing users to the desired snippet destination.
Original PR description
Issue: ------- When a zero price product is created and the contact us button on the product page is intended to redirect to some snippets created through drag and drop then the button doesn't work…
Issue: ------- When a zero price product is created and the contact us button on the product page is intended to redirect to some snippets created through drag and drop then the button doesn't work as intended meaning it doesn't redirects to the desired snippet even after putting the correct anchor. for ex: `#snippet-anchor` in the `Button URL` field in the settings. Cause: -------- This works fine for the pages having '/contactus' or '/'. Issues raise only when we try to redirect to a snippet. Now, if the we try to redirect to any snippet on click of the button(Contact Us) by placing the corresponding anchor, it will not redirect/work as intended. This is because of the appending`?subject=product_name` that took place. Solution: ------------ To concatenate the `subject=product_name` conditionally if the url has '#' in it If yes, we just use the `url` in the URL so that it redirects as intended else concatenate the subject & so on. This is because for redirecting to snippets we use anchors such as '#Let's-Connect'. So, In an anchor the '#' will definitely reside. Steps to reproduce: ----------------------- 1. Create a db in version 18.3 with website_sale installed. 2. Enable the `Prevent Sale of Zero Priced Product` checkbox in the settings. 3. Create a zero price product and few snippets under it and copy the anchor of one of the snippets to redirect when clicked on the 'Contact Us' button. 4. Use the Anchor(for ex: '#Let's-Connect') in the 'Button URL' field of settings. 5. Navigate to the created product and click on the 'Contact Us' button. Nothing happens & no intended redirection to the desired snippet. Ref PR: ---------- https://github.com/odoo/odoo/pull/189049/changes#diff-39e02d03a8b765b4e3afc68627aeb33f11b587163638fedfb92ed5657c3336e7R398-R399 Attachments: ----------------- **Before Fix:** [vokoscreenNG-2026-02-06_17-36-37.webm](https://github.com/user-attachments/assets/a09101d4-13df-415d-a902-420a28aedef0) **After Fix**: [vokoscreenNG-2026-02-06_17-38-37.webm](https://github.com/user-attachments/assets/a6256d0f-d8cb-4146-b95e-33452a0a79c5) - OPW - [5494517](https://www.odoo.com/odoo/project/70/tasks/5494517) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249906 Forward-Port-Of: odoo/odoo#247587
Miscellaneous changes
When generating the Sales Report or Session Report with a large number of orders (1000+), the report computation could take several minutes or fail entirely with cursor closed errors. This was mainly caused by multiple inefficient ORM patterns, such as repeated searches inside nested loops and unnecessary recordset instantiations. This commit optimizes the report generation logic by: - Avoiding repeated searches inside loops (e.g. account payments per session) - Using `_search` instead of `
Original PR description
When generating the Sales Report or Session Report with a large number of orders (1000+), the report computation could take several minutes or fail entirely with cursor closed errors. This was mainly…
When generating the Sales Report or Session Report with a large number of orders (1000+), the report computation could take several minutes or fail entirely with cursor closed errors. This was mainly caused by multiple inefficient ORM patterns, such as repeated searches inside nested loops and unnecessary recordset instantiations. This commit optimizes the report generation logic by: - Avoiding repeated searches inside loops (e.g. account payments per session) - Using `_search` instead of `search` where only record ids are required - Grouping and caching session-related records (payments, moves, cash moves) - Reducing redundant ORM calls and Python-level iterations - Preserving the exact report output structure and values The returned data remains unchanged; only record ordering may differ due to optimized iteration and grouping. As a result, report generation time is significantly reduced and the report can be generated reliably even with very large order counts. task-5452734 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278843 Forward-Port-Of: odoo/odoo#241828