Daily updates from Odoo
Tuesday, April 21, 2026
23 changes · saas-18.3
Enhancements to existing features
This change makes validating large stock movements much faster by processing move line removals and additions in batches instead of one by one. It reduces database calls and avoids repeated recalculations, which helps prevent timeouts on very large pickings.
Original PR description
Before this PR, `button_validate` was using a `write()` call per matched stock move. On every `write()` there is a Command.create and Command.delete which is resulting in N database round-trips for…
Before this PR, `button_validate` was using a `write()` call per matched stock move. On every `write()` there is a Command.create and Command.delete which is resulting in N database round-trips for the unlinks and N for the creates, followed by N separate `_apply_putaway_strategy()` calls. This is problematic for pickings with many move_ids. This PR attempts to accumulates all move lines to delete and to create. Then performs a single `unlink()` and `create()`, followed by a single `_apply_putaway_strategy()` for all pickings. Unlink is done using `.sudo()` to preserve the superuser context that was previously inherited implicitly through the `purchase_order.sudo().search` that produced the recordset used to obtain the `receipt_move`(s). Benchmarks: | No. move lines in delivery | Before | After | | -------------------------- | ------- | ----- | | 7579 | Timeout | < 200 s | opw-5826905 Forward-Port-Of: odoo/enterprise#110587 Forward-Port-Of: odoo/enterprise#110153
Resolved issues and error corrections
This update preserves the visual link styling in frozen and shared spreadsheets while keeping those links inactive for public viewers. It fixes a layout regression so dashboards continue to look consistent without exposing clickable internal links.
Original PR description
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that…
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that we'd somehow leak internal views information in the links), cells with links benefit from a specific style that is not hardcoded on the cell but rather computed based on their content. By removing the links from teh cells altogether, the greenish link style is lost on those cells and we actually rely on that style for our dashboards layout. To preserve the intension of https://github.com/odoo/odoo/pull/166843, we introduce a new type of links `neutralized` which allows the cell to be recognized as a link (and benefit from the style) while disabling their behaviour (no click). Task-6063301 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#260099 Forward-Port-Of: odoo/odoo#256357
The salary package test no longer depends on sample/demo records being present. It now creates its own test data, which makes the test more reliable in environments where demo data is disabled.
Original PR description
### Issue: - We were referring an existing XML ID in our test case, but that record is only created in demo data. ### Fix: - No need to use the demo record Id, instead, create a new record. Task: 6115762 Forward-Port-Of: odoo/enterprise#114312 Forward-Port-Of: odoo/enterprise#113622
Opening a shared helpdesk ticket link will no longer fail if the original message author has been deleted. The system now safely skips missing author details, preventing an error and keeping the ticket accessible to users.
Original PR description
Currently, an error occurs when opening a shared helpdesk ticket link if the message author has been deleted. **Steps to Reproduce:(v19.2)** - Install Contacts and Helpdesk modules (with demo data). - Log in as "**Marc Demo**". - Create a helpdesk ticket and send a message via the chatter. - Log in as **Admin**. - Delete the demo user and the related partner from Contacts. - Go to Helpdesk > All Tickets and open the created ticket. - Click "**Share Ticket**" and open the generated link in another browser. Error: `ValueError - Expected singleton: res.partner()` **Cause:** When the partner linked to `message.author_id` is deleted, the recordset becomes empty, which raises a singleton error. Fix: This commit ensures that the author details are only included when the message author exists. sentry-7337698605 Forward-Port-Of: odoo/odoo#259680 Forward-Port-Of: odoo/odoo#254175
Generating a W-2 CSV now works even when the report’s end date is left blank. If no end date is provided, the system uses the current year for the file name instead of failing, making the report more reliable for users.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#113408This change prevents a crash when searching for an employee in Attendance kiosk mode. It makes the search more resilient by ignoring invalid filter items, so users can complete the lookup without encountering an error.
Original PR description
**Steps to Reproduce:**
1. Install `hr_attendance` module with demo data.
2. Go to Attendances > Kiosk Mode > Identify Manually.
3. Select any department.
4. Try searching for an employee.
**Error:**
`ValueError - not enough values to unpack (expected 3, got 1)`
**Cause:**
The `employees_infos()` controller assumes that every item in the domain is a valid triplet (field, operator, value). However, the domain may also contain logical operators ('&'), which are not triplets. And then trying to unpack such entries leads to a ValueError.
**Fix:**
Add a validation to ensure the condition is a proper triplet before unpacking. Non-conforming entries (logical operators) are skipped.
sentry-7401444075
opw-6113268
Forward-Port-Of: odoo/odoo#258825This change prevents the website cookie banner from saving an outdated value when it is closed indirectly, such as when opening the search panel. It helps avoid repeated cookie updates behind the scenes, which can otherwise cause server header size issues on some setups.
Original PR description
Steps to reproduce: - Set the cookies bar - Do not accept nor reject it - On the website homepage, click on the search button => Check the cookies: website_cookies_bar=true is set. `Popup`…
Steps to reproduce: - Set the cookies bar - Do not accept nor reject it - On the website homepage, click on the search button => Check the cookies: website_cookies_bar=true is set. `Popup` initializes `cookieValue` to `true` and writes it in `onHideModal()`. If the cookies bar is closed before any explicit consent choice, it can therefore recreate the legacy invalid value `website_cookies_bar=true`. This happens because the search button uses `data-bs-toggle="modal"`, which is controlled by Bootstrap: if it is opened while another bootstrap modal is already open on the page, the latter is hidden. This in turn calls the popup interaction's `onHideModal()`, which sets `website_cookies_bar=true` as `cookieValue` hasn't been changed. That value is later treated as invalid and cleared repeatedly during website rendering, which can accumulate duplicate `Set-Cookie` headers in the same response and lead to `upstream sent too big header` behind nginx. Avoid persisting that legacy value by returning early from `CookiesBar.onHideModal()` while `cookieValue` is still the inherited default `true`. opw-6037573 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Backport of: https://github.com/odoo/odoo/pull/258938 Forward-Port-Of: odoo/odoo#259717 Forward-Port-Of: odoo/odoo#259585
This fix makes sure attachments keep their originally provided file type information when they are uploaded to cloud storage. It prevents the system from re-detecting or changing the file type, which helps keep documents classified correctly and avoids inconsistencies for users.
Original PR description
When uploading an attachment to cloud storage via `_post_add_create(cloud_storage=True)`, the attachment's original `mimetype` is guessed even if we specify it. With this commit we explicitly preserve given mimetype Discovered during task-5153790 Forward-Port-Of: odoo/odoo#257979
This change blocks combo products from being selected directly in the mobile sales order line form. It prevents lines from being created with no price and no linked components, avoiding confusing and incomplete orders.
Original PR description
Combo products bypasses the configurator in mobile view, resulting in a 0-price line with no child lines. Exclude them via domain on the field. opw-5999935 Forward-Port-Of: odoo/odoo#256790
Access errors now point to the real rule blocking a record, instead of incorrectly implying a company-related problem. This makes troubleshooting clearer for users and reduces confusion when archived records are involved.
Original PR description
When accessing an archived record directly, if access is prevented by a record rule other than a multi-company global rule, the error message incorrectly reports that all rules are failing, suggesting a company issue even though it is not the actual cause. The problem is that when access is denied, the diagnostic method `_get_failing` is used to determine which rules are failing. This method performs several count queries with different rule domains. However, `active_test` is True by default, excluding archived records from the count, causing the rule evaluation to miss some records and incorrectly mark rules as failing. With this commit, `_get_failing` evaluates rules with `active_test=False`, ensuring that only actually failing rules are reported. Forward-Port-Of: odoo/odoo#259592 Forward-Port-Of: odoo/odoo#259344
This change corrects how self-billed invoices are matched in setups with multiple companies on Peppol. It ensures each invoice is assigned to the right company, avoiding mispostings and accounting confusion.
Original PR description
Currently, if a database has multiple companies registered on Peppol, receiving a self-billed invoice may assign it to the wrong company. The system was searching the journal using a domain that included all companies (in self), instead of filtering by the correct current company. Steps to reproduce: - Create a database with 2 companies, both on Peppol - Receive a self-billed invoice from a random other company on Peppol - The received invoice will potentially be assigned to the wrong company This is only a test forward-port of #257380 opw-6045669 Forward-Port-Of: odoo/odoo#259072
This update refreshes the spreadsheet component to its latest version and includes several fixes to improve reliability. It helps prevent crashes, avoids copy/paste issues between versions, and reduces visual glitches in the spreadsheet interface.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/f67756809c [REL] 18.3.43 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/f67756809c [REL] 18.3.43 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/7c13cca1f5 [IMP] package: backport rolldown and TS 6.0 [](https://www.odoo.com/odoo/2328/tasks/) https://github.com/odoo/o-spreadsheet/commit/3d605a6739 [IMP] typescript: upgrade to 6.0.2 [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/83d8c6b8fc [FIX] package: add rolldown binaries to optional dependencies [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/d40fcccb5a [IMP] package: upgrade rolldown to latest version [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/1efd2ccd33 [IMP] config: rename rolldown config file [Task: 6071659](https://www.odoo.com/odoo/2328/tasks/6071659) https://github.com/odoo/o-spreadsheet/commit/093fd55760 [IMP] config: replace rollup with rolldown [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/02e49398f1 [IMP] eslint: enforce type exports [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/7521d5e12c [IMP] pre-commit: bypass eslint's typescript compilation [](https://www.odoo.com/odoo/2328/tasks/) https://github.com/odoo/o-spreadsheet/commit/c8aa3813ef [REF] *: apply eslint to entire codebase [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/24afb2933c [IMP] config: Fix eslint to work alongside typescript [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/1091562b49 [IMP] tsconfig: moduleResolution bundler [Task: 6119495](https://www.odoo.com/odoo/2328/tasks/6119495) https://github.com/odoo/o-spreadsheet/commit/c8e5617dd4 [FIX] spreadsheet_pivot: avoid crash on invalid dimension values [Task: 6111913](https://www.odoo.com/odoo/2328/tasks/6111913) https://github.com/odoo/o-spreadsheet/commit/77a7f00b12 [FIX] side_panel: prevent chart picker layout shift on hover [Task: 6095239](https://www.odoo.com/odoo/2328/tasks/6095239) https://github.com/odoo/o-spreadsheet/commit/1ba7513a50 [FIX] clipboard: prevent cross-version copy/paste [Task: 6095101](https://www.odoo.com/odoo/2328/tasks/6095101) https://github.com/odoo/o-spreadsheet/commit/30ac20d3ca [IMP] tests: add tests for `chartShowValuesPlugin` [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/0f8f7c632e [FIX] computed style: fix multi-user clear formatting [Task: 6086129](https://www.odoo.com/odoo/2328/tasks/6086129) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
The table editing menu now refreshes its options when the selected cell changes. This prevents outdated choices from appearing and helps users apply the right table actions more reliably.
Original PR description
After this commit [1], setup is executed only on the initial mount of the table menu and not on subsequent target cell changes. As a result, colItems, rowItems, and other values found in setup become stale, causing the menu to display options that do not reflect the current target cell. This commit moves the necessary values from setup into useEffect so they update correctly when the target cell changes. task-6111986 [1]: https://github.com/odoo/odoo/commit/7d523d6402c9bff3c2e4bcd0329f486a2d0f45ec Backport of Commit https://github.com/odoo/odoo/commit/729c45ddf3d1e377507d93997c5ca45984d64d75 Forward-Port-Of: odoo/odoo#259431 Forward-Port-Of: odoo/odoo#258590
This change fixes a flaky test in the website editor that could pass or fail depending on how quickly the system reacted. It now behaves more like a real user click, making the test results more reliable and reducing false failures in automated checks.
Original PR description
The popover opening is triggered through click, but there is a selectionchange handler on click that checks if the selection is outside of the link and, if it is, closes the popover. In this case, the click method didn't set the selection inside the link properly because of the presence of \ufeff around the link. The test actually passes by mistake when the runbot was fast, but failed when the runbot was slow, as the selectionchange handler had the time to execute and close the popover. This commit forces the selection to be inside the link after calling click, to be closer to what actually happens when a user click on a link, as opposed to a programmatic click. runbot-161423 Forward-Port-Of: odoo/odoo#259688
The web client now correctly handles action buttons even when they do not have a visible label. This ensures the system can tell whether a close or discard button triggered the callback, improving reliability in user flows that depend on that result.
Original PR description
View buttons with no name cause onClosed to be called without any parameters even if special=true or dismiss=true. This commit fixes that which allows to know if a close/discard button caused the action onClosed callback. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change reverts a previous adjustment that caused child contact display names to appear incorrectly. It helps ensure customer and invoice information is shown in the expected format again, reducing confusion in printed documents and business records.
Original PR description
This reverts commit 0ef4c1d06fdf999ad5cdad696069aec8f2f943c5. opw-5900567 Forward-Port-Of: odoo/odoo#260097 Forward-Port-Of: odoo/odoo#260065
This fix corrects how activity filters are combined in Studio-created apps. Previously, "My Activities" could be mixed with "Late Activities" in a way that showed too many records; now the filters work together as expected, improving the accuracy of task and activity views.
Original PR description
Follow-up of 475a9efe0bde7515c9d5bf6ec6c8aefd4c71975e Steps to reproduce ================== - Create an app with studio and use_mail - Create three records, one with an activity in the past, one today and one in the future - Click on the clock status icon in the top right - There should be a section with the new model - Click on 1 Late => every records is displayed The filters "My Activities" is combined with "Late Activities" with and OR. It should use the AND operator. Solution ======== Add a separator after the "My Activities" filter. The same is done in xml for standard models. opw-6069150
This fix stops Discuss from crashing when records are deleted in the background. It also prevents the wrong item from being removed in certain cases, which could leave the interface in an inconsistent state.
Original PR description
Backport of https://github.com/odoo/odoo/pull/251769 Before this commit, Discuss code may crash with the following error: ```js TypeError: Cannot read properties of undefined (reading '_raw') ```…
Backport of https://github.com/odoo/odoo/pull/251769 Before this commit, Discuss code may crash with the following error: ```js TypeError: Cannot read properties of undefined (reading '_raw') ``` This happens because delete operations in JS models could lead to inconsistent state of record lists. Deletion of a record is done internally as follow: ```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 might happen with deletion of any item in record list. For example, let's have `menuThreads` that have this value: ```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. Task-4793779 Forward-Port-Of: odoo/odoo#260109
When a sales order for a subcontracted service is increased, the related purchase order now uses the correct quantity. This prevents the system from multiplying the extra quantity twice and creating an unexpectedly large purchase order.
Original PR description
Steps to reproduce the bug: - Create a service product "P1": - In the Purchase tab: - Vendor: Azure Interior - Subcontract Service: True - UoM: dozen - Purchase UoM: unit - Create a sales order with…
Steps to reproduce the bug:
- Create a service product "P1":
- In the Purchase tab:
- Vendor: Azure Interior
- Subcontract Service: True
- UoM: dozen
- Purchase UoM: unit
- Create a sales order with 1 dozen of P1
- Confirm -> a purchase order with 12 units of P1 is generated
- Confirm the purchase order
- Go back to the sales order:
- Update the quantity from 1 to 2 dozen
Problem:
A new purchase order is generated, but with 144 units instead of 12
units. The quantity difference between the old SO quantity and the new
one is computed twice in the purchase order line UoM, in both
`_purchase_increase_ordered_qty` and `_purchase_service_prepare_line_values`:
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L186
Solution:
The `quantity` parameter must be expressed in the SO line UoM, as
described in the documentation of the function `_purchase_service_prepare_line_values`.
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L178
opw-6049106
Forward-Port-Of: odoo/odoo#257637
Forward-Port-Of: odoo/odoo#255478This change fixes an access problem that prevented some users from printing product and product variant labels, even when they only needed to view the products. It restores the expected behavior so staff with read access can use label printing without needing extra permissions.
Original PR description
Users who do not have the "write" access on `product.template` and `product.product` cannot print product labels and product variant labels Steps to reproduce: 1. Install Sales 2. Log in as Marc Demo…
Users who do not have the "write" access on `product.template` and `product.product` cannot print product labels and product variant labels Steps to reproduce: 1. Install Sales 2. Log in as Marc Demo 3. In Sales > Products > Products, open a product and click Print Labels from the cogwheel menu 4. An access error is raised Same issue happens for Product Variants Issue: https://github.com/odoo/odoo/commit/95ace0a694eaf83329b50e6b89f774f0c59fec5e removed Products-related rights from the `base.group_user`. This made a difference in terms of access rights, as the `IrActionServe.run` method checks for the "write" access by calling `_can_execute_action_on_records`: https://github.com/odoo/odoo/blob/d15685304f479541879fabd55ea1cae4252a2a90/odoo/addons/base/models/ir_actions.py#L1230-L1239 Solution: Add `group_user` to the `group_ids` of the relevant actions to prevent the check on the "write" access from being performed This is a backport of https://github.com/odoo/odoo/commit/6c2c353f30db05579f5e8b7a6752ec2d1ae365b2 opw-6111333
This change corrects a test setup issue in the UBL export module so it no longer fails while checking required security groups. It helps keep automated tests stable and prevents false failures during installation checks.
Original PR description
The `get_default_groups` call happens during super.setUpClass(), therefore we have not checked (yet) if the module in which the security group is in is installed, and we end up with an Exception. task-none Forward-Port-Of: odoo/odoo#260230
Auto-completing a vendor bill now correctly keeps its Intrastat information when the source bill already had it. This prevents missing trade reporting data and helps ensure the generated bill is complete and compliant.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
This fix prevents an error when exporting the General Ledger in a Peru company if draft invoices or other draft entries are included. Users can now complete the export without the report breaking, improving reliability for accounting work.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405