Daily updates from Odoo
Friday, July 24, 2026
197 changes
15 changes
Resolved issues and error corrections
The Related Entries button for confirmed assets has been renamed to Related Items and now keeps users in the journal item list instead of opening an unhelpful detail form. This makes reviewing asset-related accounting lines clearer and reduces unnecessary navigation.
Original PR description
If you create an asset and confirm it, you can see the Related Entries using the smart button Related Entries. The list view that opens is clickable, but it opens a quite useless form view of the Journal Items. - Rename breadcrumb button to Related Items - Make it behave like action_account_moves_all, to not open form view Ticket: [6385260](https://www.odoo.com/odoo/project/967/tasks/6385260) Forward-Port-Of: odoo/enterprise#124672
This fixes an intermittent issue in automated barcode scrap checks where the entered scrap quantity could be lost before saving. The change helps keep test results reliable and reduces false failures in inventory and manufacturing barcode workflows.
Original PR description
These barcode scrap tours randomly trigger "You can only enter positive quantities." on runbot: the quantity set with a raw input.value is dropped when the field re-renders before the scrap is saved, so it scraps 0. Dispatching an input event keeps the typed value. error-238911 Forward-Port-Of: odoo/enterprise#124952
The project forecasting view was updated so it connects to the current subtask button. This prevents the button customization from pointing to an outdated action and helps users access subtasks reliably.
Original PR description
Issue --- The inherited xpath still targets the old action-based subtask button Fix --- Update the inherited xpath to target action_open_subtasks. task-5966684 Forward-Port-Of: odoo/enterprise#124063 Forward-Port-Of: odoo/enterprise#123035
Fixed an issue where testing a CSV import of bank statement lines could fail because temporary imported records were incorrectly reused after rollback. This makes bank statement imports more reliable and prevents confusing errors during import validation.
Original PR description
odoo/odoo#255059 made execute_import's savepoint flushing, so a dryrun rollback now properly invalidates the ORM cache instead of leaving it. That exposed a pre-existing bug here: we created the statement with line_ids pointing at .line records dryrun had already rolled back, raising "Record does not exist or has been deleted". To fix this issue we run as dryrun as False to allow the execute_import's savepoint do the work and rollbacked in finally. Steps to reproduce: - Just import a account.bank.statement.line OPW-6410352
Odoo Studio now allows users to rename fields with labels using Arabic or other non-Latin characters without causing an invalid technical name error. This prevents a confusing failure when customizing views for multilingual users.
Original PR description
Steps: - Install web_studio - Add any field (example char field) to any view - Rename it in arabic, example `السَّلَامُ عَلَيْكُمْ` - Error Custom field names cannot contain double underscores Webclient (view_editor_model) escape every non-alphabetic chars, so new label value contains nothing but a space which will be replaced by a _ this new label value will be concatenated to `x_studio_`. Resulting to the string `x_studio__`. A solution should be to prevent changing the technical name if the new label value (escaped) is empty. opw-6311027 Forward-Port-Of: odoo/enterprise#124445 Forward-Port-Of: odoo/enterprise#121343
The timesheet completion percentage now updates immediately when timesheets are added, changed, or removed. This keeps project or task progress information accurate on screen without requiring users to refresh the page.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186 Forward-Port-Of: odoo/enterprise#125312 Forward-Port-Of: odoo/enterprise#125074
This fix ensures the BA zone in French VAT reports is sent in the expected free-text format rather than as a standard value. It helps avoid formatting or submission issues when preparing compliant French tax reports.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id Forward-Port-Of: odoo/enterprise#125335
Audit reports now refresh the number of invalid records when a check is reviewed successfully. This prevents users from seeing outdated issue counts after a check has been corrected, improving confidence in audit results.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177 Forward-Port-Of: odoo/enterprise#123976 Forward-Port-Of: odoo/enterprise#119227
Users opening an account report from the VAT return check can now refresh the page without triggering an error. This improves reliability for accounting workflows by preserving the report view correctly.
Original PR description
Opening an account report through the VAT return button on an account.return.check record returns an inline client action whose report_id only exists in context. On refresh, Odoo will throw an error because it will try to rebuild the action context based off of the URL which is deficient. This will not effect reports opened via the menu since those follow a different pathway. This fix anchors the inline action to the "path" property stored on the client action. A helper method was added for deriving the action_id from a given report. opw-6366964 Forward-Port-Of: odoo/enterprise#125246 Forward-Port-Of: odoo/enterprise#124560
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure t
Original PR description
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027.…
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure the certificate for Ticketbai works) 3. Go to Settings → Spain Localization → set Tax Agency for = Bizkaia 4. Change VAT number for customer Mulhacén Digital S.L. into N0011452J (must be a foreign entity ID) 5. Go to Settings > Technical > System Parameters and set the parameter 'l10n_es_edi_tbai.epigrafe' to 165360 6. Create a new invoice for that client and try to send it to TicketBAI 7. Error: B4_1000002: Todos los registros incluidos en la petición son incorrectos. B4_2000027: La factura contiene un Tipo de desglose incorrecto. Ha de ser a nivel de operación cuando la factura es completa y, además, existe destinatario extranjero (tipo IDOtro o que sea NIF que empiece por N) o la Clave de IVA es 02. ### Cause of the issue: The _l10n_es_is_foreign() method evaluated these customers as domestic because their country was set to Spain and their VAT did not start with "ESN". It failed to recognize a standalone "N" prefix as a valid foreign identifier. https://github.com/odoo/odoo/blob/75ae45861e2f417aa2b90bdb2b2869718e091c09/addons/l10n_es/models/res_partner.py#L7-L10 ### Reason to introduce the fix: Adding the 'N' prefix to the _l10n_es_is_foreign() check ensures the system correctly treats these entities as foreign for tax purposes. This generates the correct XML structure automatically, without forcing users to unnaturally prepend "ES" to a legally valid NIF. opw-6326359 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277816 Forward-Port-Of: odoo/odoo#275231
Issue: - After confirming a sale order with a reward applied (e.g. an ewallet reward), unlocking it, and editing it so the reward line's cost changes (e.g. adding a product and re-claiming the reward), the coupon's point balance updates correctly. - However, the corresponding loyalty.history record's used value is never refreshed, so it keeps showing the old cost instead of the new one. Steps to reproduce: - Enable Loyalty and Lock Confirmed Sales in Sales settings. - Create an ewallet ty
Original PR description
Issue: - After confirming a sale order with a reward applied (e.g. an ewallet reward), unlocking it, and editing it so the reward line's cost changes (e.g. adding a product and re-claiming the…
Issue: - After confirming a sale order with a reward applied (e.g. an ewallet reward), unlocking it, and editing it so the reward line's cost changes (e.g. adding a product and re-claiming the reward), the coupon's point balance updates correctly. - However, the corresponding loyalty.history record's used value is never refreshed, so it keeps showing the old cost instead of the new one. Steps to reproduce: - Enable Loyalty and Lock Confirmed Sales in Sales settings. - Create an ewallet type loyalty.program and generate an ewallet for a partner with e.g. 1000 points. - Create a sale order for that partner, add a product worth 100, and claim the ewallet reward (reward line created with points_cost = 100). - Confirm the order. loyalty.history shows used = 100 (correct), card balance shows 900 (correct). - Unlock the order, add a second product worth 100, and claim the reward again (same reward line updates to points_cost = 200). - Lock the order again. - Check the loyalty.card: balance is correctly 800. - Check loyalty.history for that order: used still shows 100 instead of 200. Fix: - Updated _update_loyalty_history() in sale_order.py to create a new history line if none exists for the given card and order combination. - Updated write() in sale_order_line.py to correctly sync history lines when a reward line is modified on a confirmed order, handling both same-coupon updates via delta and coupon changes by subtracting the old coupon cost and adding the new one separately. - Added test_loyalty_history_created_on_post_confirm_reward to verify that a history line is created when a reward is claimed on a confirmed order where no history line existed before. - Added test_loyalty_history_updated_on_points_cost_write to verify that history.used is updated by the correct delta when points_cost changes on a reward line of a confirmed order. Impact: - Ensures a coupon's usage history stays accurate after a confirmed order is unlocked and edited. - Prevents the loyalty.history used field from silently going stale while the actual point balance is correct. - Not scoped to ewallet specifically — since points_cost semantics are the same across program types, this also corrects the same class of staleness for other reward types (discount, gift_card, etc.) when a reward line's cost changes post-confirmation. Forward-Port-Of: odoo/odoo#277450 Forward-Port-Of: odoo/odoo#273688
2 props were misconfigured: - `countryID` Previous fix: https://github.com/odoo/odoo/commit/319bb52dcb022bd67b0d7349d5720221d6e1d7c4 made it so `country_id` would correctly register as a "many2one", but this made it conflict when it was passed as a `countryId` prop which expects it to be a number, rather than a many2one object. - `selectedLocationId` OWL3 conversion in https://github.com/odoo/odoo/commit/55fd748ada717df5b27376c81a8eba53d9b8ddac incorrectly converted `selectedLocationId` to
Original PR description
2 props were misconfigured: - `countryID` Previous fix: https://github.com/odoo/odoo/commit/319bb52dcb022bd67b0d7349d5720221d6e1d7c4 made it so `country_id` would correctly register as a "many2one",…
2 props were misconfigured: - `countryID` Previous fix: https://github.com/odoo/odoo/commit/319bb52dcb022bd67b0d7349d5720221d6e1d7c4 made it so `country_id` would correctly register as a "many2one", but this made it conflict when it was passed as a `countryId` prop which expects it to be a number, rather than a many2one object. - `selectedLocationId` OWL3 conversion in https://github.com/odoo/odoo/commit/55fd748ada717df5b27376c81a8eba53d9b8ddac incorrectly converted `selectedLocationId` to `optional(false) https://github.com/odoo/odoo/blob/f5c1d2210f18d1644a7ce67fca806f5c5db3df69/addons/website_sale_stock/static/src/js/location_selector/location_selector_dialog/location_selector_dialog.js#L11-L16 Steps to reproduce: - Create new Sales Order - Add a customer + product of type "Goods" - Click "Add shipping" and select "Pick up in store" delivery method - Click on Pencil button in same row as "Pickup Point" field Expected Behavior: Pickup Location selector dialog should open Actual Behavior: Stacktrace due to `"selectedLocationId", "message": "value is not a string"` or `"countryId", "message": "value is not a number"` Note that error doesn't occur when selecting pick up points via the website (i.e. ecommerce flow), possibly due to the props enforcement not occurring in the front end. opw-6321167 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
On a Purchase Order, if you duplicate the delivery, change its Operation Type and validate it, it will still count towards the received quantity on the po. Steps to reproduce: ------------------- * Create a PO and confirm it * Open the receipt, validate and duplicate it * Go on the duplicated receipt and change its Operation Type * Confirm the duplicated receipt. -> the Received Qty on the Po counted the duplicated and modified transfer. Observation: ------------- When we duplicat
Original PR description
On a Purchase Order, if you duplicate the delivery, change its Operation Type and validate it, it will still count towards the received quantity on the po. Steps to reproduce: ------------------- *…
On a Purchase Order, if you duplicate the delivery, change its Operation Type and validate it, it will still count towards the received quantity on the po. Steps to reproduce: ------------------- * Create a PO and confirm it * Open the receipt, validate and duplicate it * Go on the duplicated receipt and change its Operation Type * Confirm the duplicated receipt. -> the Received Qty on the Po counted the duplicated and modified transfer. Observation: ------------- When we duplicate a stock.picking, we will call ```copy``` and copy all its ```move_ids``` (stock.move), and in stock.move we will copy the ```purchase_line_id``` : https://github.com/odoo/odoo/blob/754898c58fded0e3c3c30702f15258f1dadcfa6c/odoo/models.py#L5868 https://github.com/odoo/odoo/blob/754898c58fded0e3c3c30702f15258f1dadcfa6c/odoo/models.py#L5881-L5892 https://github.com/odoo/odoo/blob/3e6d93bef49bb2718e8aa1756f95c2a6117c8d55/addons/purchase_stock/models/stock_move.py#L13-L15 the ```purchase_line_id``` will keep the link with the pol. The fields are copied since they have ```copy=True``` https://github.com/odoo/odoo/blob/754898c58fded0e3c3c30702f15258f1dadcfa6c/addons/stock/models/stock_picking.py#L614 https://github.com/odoo/odoo/blob/754898c58fded0e3c3c30702f15258f1dadcfa6c/odoo/fields.py#L304 Because new stock moves are linked directly to the Purchase Order Line (POL), the qty_received calculation aggregates all associated move quantities. https://github.com/odoo/odoo/blob/cfc63060926db4cec773c159b8ecf97dc0b36d1a/addons/purchase_stock/models/purchase_order_line.py#L73-L76 opw-6088239 Forward-Port-Of: odoo/odoo#276250 Forward-Port-Of: odoo/odoo#259570
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is undefined" crash. Steps to reproduce ================== 1. Open a product and edit its image 2. In "Select a media", search a term (e.g. "new") 3. Click one of the online library illustrations => The wrong image is saved, or an error notification is shown Root cause ========== Library media r
Original PR description
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is…
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is undefined" crash. Steps to reproduce ================== 1. Open a product and edit its image 2. In "Select a media", search a term (e.g. "new") 3. Click one of the online library illustrations => The wrong image is saved, or an error notification is shown Root cause ========== Library media results carry a media-library id, not a local ir.attachment id. imageSave persists them as real attachments (save_library_media, run inside super.save) but then reads them back using the original media-library id. That id either collides with an unrelated local attachment, e.g. a type='url' demo record with no raw, hence the wrong image and the "reupload" warning or matches no record at all, so the read returns undefined and accessing .raw throws. Fix === Use the ids of the attachments actually created by the render step, carried on the rendered <img> elements (dataset.attachmentId), instead of the media-library ids. opw-6353273 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274372
Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal access rights (only access rights to their own sales orders and invoices). 2. Sign in as that user and create a sales order and confirm it. 3. Create an invoice for that sales order and validate it. 4. Sign in as an administrator and create a duplicate sales order for that sales order, but as
Original PR description
Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal…
Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal access rights (only access rights to their own sales orders and invoices). 2. Sign in as that user and create a sales order and confirm it. 3. Create an invoice for that sales order and validate it. 4. Sign in as an administrator and create a duplicate sales order for that sales order, but assign it to a different user (not the one created in step 1). 5. Confirm the duplicate sales order, create an invoice for it and validate it. 6. Sign in as the user created in step 1 and try to access the invoice created in step 3. 7. Note the access error Cause: When reading an account.move record, the system searches for duplicate moves and adds them to the duplicated_ref_ids field. However, it does not check if the user has read access to those duplicate moves, which leads to access errors when trying to access the main account.move record (which the user has read access to) because the system tries to read the duplicate moves (which the user does not have read access to). opw-6374566 Forward-Port-Of: odoo/odoo#277823 Forward-Port-Of: odoo/odoo#276547
11 changes
Resolved issues and error corrections
The salary attachment form now shows the refund option again, matching the information already stored in the system. This helps payroll users correctly identify refund-related salary attachments without needing a separate wizard or workaround.
Original PR description
In an old PR (https://github.com/odoo/enterprise/pull/109195) the is_refund field was removed from the salary attachment view, although the field itself was not removed from the db. In a later PR (https://github.com/odoo/enterprise/pull/114188) the field was removed from the database but later reverted (https://github.com/odoo/enterprise/pull/123728). As it stands now, the field is in the database and is present in the view of a wizard but not in the standard form view of the salary attachment. This PR is reintroducing it. Task: 6415857
The timesheet percentage now refreshes as soon as timesheets are added, edited, or removed, instead of waiting for a page reload. This keeps sales and project tracking information accurate in real time and reduces confusion for users.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186 Forward-Port-Of: odoo/enterprise#125224 Forward-Port-Of: odoo/enterprise#125074
This fixes intermittent failures in automated barcode scrap checks that could incorrectly treat a scrap quantity as zero. The change helps keep stock and manufacturing barcode validation more stable, reducing false alarms in quality checks.
Original PR description
These barcode scrap tours randomly trigger "You can only enter positive quantities." on runbot: the quantity set with a raw input.value is dropped when the field re-renders before the scrap is saved, so it scraps 0. Dispatching an input event keeps the typed value. error-238911 Forward-Port-Of: odoo/enterprise#124952
When users open related entries from a confirmed asset, the list now stays focused on the relevant journal items instead of opening an unhelpful detail form. The breadcrumb label is also clearer, using “Related Items” to better describe what users are viewing.
Original PR description
If you create an asset and confirm it, you can see the Related Entries using the smart button Related Entries. The list view that opens is clickable, but it opens a quite useless form view of the Journal Items. - Rename breadcrumb button to Related Items - Make it behave like action_account_moves_all, to not open form view Ticket: [6385260](https://www.odoo.com/odoo/project/967/tasks/6385260) Forward-Port-Of: odoo/enterprise#124672
Audit reports now correctly update the number of invalid records when an audit check is reviewed successfully. This prevents users from seeing outdated anomaly counts after a check no longer finds issues, improving confidence in audit cycle reporting.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177 Forward-Port-Of: odoo/enterprise#123751 Forward-Port-Of: odoo/enterprise#119227
This fixes the French VAT report export so the BA zone is sent using the expected free-text format rather than as a standard value. This helps ensure the generated report matches the required filing structure and reduces the risk of submission errors.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id Forward-Port-Of: odoo/enterprise#125335
The SEO autofill powered by AI now uses the website page’s language instead of the editor’s personal language setting. This helps multilingual websites generate page titles and descriptions in the correct language, reducing manual correction and improving consistency for visitors and search engines.
Original PR description
The SEO "Fill with AI" autofill used the user's language for generation. On a website whose language differs from the user's, the generated seo metadata was therefore in the wrong language. This commit fixes this by using the page language instead. Forward-Port-Of: odoo/enterprise#123447
This fix ensures financial reports correctly recognize when no report section has been opened yet. It helps preserve expected report navigation behavior and prevents a small logic issue from affecting how report sections are restored or displayed.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**
Forward-Port-Of: odoo/enterprise#125325
Forward-Port-Of: odoo/enterprise#124223This fix prevents leftover collaboration messaging from one automated test interfering with a Knowledge tour that does not use collaboration. It helps keep automated build checks stable and reduces false failure reports during testing.
Original PR description
This aims to fix Runbot build error #937788 ([1]). A collaboration error was thrown during a tour which makes no use of collaboration. This makes sure the bus from the previous test doesn't persist when running this tour so it doesn't interfere. [1]: https://runbot.odoo.com/odoo/runbot.build.error/937788
The timesheet assistant now expands the description field dynamically so longer entries can be read in full instead of being cut off. This makes it easier for users to review and confirm detailed time entries without losing important context.
Original PR description
- changed the description field to expand dynamically to display long descriptions in full instead of truncating them in the assistant Task-6348575 Forward-Port-Of: odoo/enterprise#123428
The test read the field content for the last urgent save right after resolving modifyImagePromise, without waiting for the DOM to actually reflect the new image src. This raced the async update of the editable content, so beforeUnload sometimes ran before the image src were updated, sending stale content and failing intermittently. Wait for the updated image to appear in the DOM before triggering the last beforeUnload, instead of relying on a fixed animationFrame wait. runbot-243773 ---
Original PR description
The test read the field content for the last urgent save right after resolving modifyImagePromise, without waiting for the DOM to actually reflect the new image src. This raced the async update of the editable content, so beforeUnload sometimes ran before the image src were updated, sending stale content and failing intermittently. Wait for the updated image to appear in the DOM before triggering the last beforeUnload, instead of relying on a fixed animationFrame wait. runbot-243773 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278032
4 changes
Resolved issues and error corrections
The Time Off overview no longer shows leave entries that fall completely outside the selected date filter. This prevents confusing leave indicators from appearing in the first visible day when managers or employees review a filtered period.
Original PR description
Steps to reproduce:-
1. Navigate to Time Off -> Overview.
2. Apply filter just after leave date.
Ex:- If there is a leave from 6th-8th july then apply filter from
9th July to 31st july.
3. You will see the leave pill on 9th July cell!
Root Cause:-
HrHolidaysGanttModel overrode _getDomain() to return the raw search
domain only, dropping the date-window clause (date_start < globalStop
AND date_stop >= globalStart) that GanttModel normally adds. As a
result, get_gantt_data returned leaves regardless of the requested
gantt range, so a leave entirely before the visible window still
showed up as a pill on the first visible cell.
Fix:-
Removed the override so the base class date filtering applies again.
task-6344353Planning kanban cards now show allocated time in a simpler, consistent format such as (4h30). The percentage value was removed to avoid uneven spacing and make the cards easier to scan.
Original PR description
Currently, the allocated hours and allocated percentage are misaligned in the planning kanban card, causing them to appear uneven or have inconsistent spacing. This fix removes the allocated percentage and formats the allocated hours to display like (4h30). task-5085363 Forward-Port-Of: odoo/enterprise#123352 Forward-Port-Of: odoo/enterprise#98776
Philippines check printing now rounds the cents portion of amounts in words to two decimal places, even when the currency is configured with more precision. This prevents checks from showing confusing or incorrect fractional amounts such as 1268/100 instead of 13/100.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#122581 Forward-Port-Of: odoo/enterprise#121913
Scenario: - create a website with main language different than en_US - create a website.page with some content - translate that page into English (en_US) - do some change in that page in original language => those changes are saved as delayed translations in en_US - from the backend, do a change in the corresponding view and save Result: the delayed changes in translation are lost and removed from all languages (even from the main website language). Cause: the backend view is displayed and sa
Original PR description
Scenario: - create a website with main language different than en_US - create a website.page with some content - translate that page into English (en_US) - do some change in that page in original language => those changes are saved as delayed translations in en_US - from the backend, do a change in the corresponding view and save Result: the delayed changes in translation are lost and removed from all languages (even from the main website language). Cause: the backend view is displayed and saved in en_US without the delayed changes. So if we modify the view and save, the view without the delayed change will be synced to all other languages which removes the delayed changes. opw-5938871 opw-6360011 Forward-Port-Of: odoo/odoo#277070
28 changes
Resolved issues and error corrections
Signed PDFs using emSigner now show the certificate in the correct position after recent emSigner interface and API changes. This helps keep completed documents looking professional and avoids confusion caused by misplaced certificate details.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
Embedded views in Knowledge now keep their intended top alignment when they appear as the first editable item. This avoids a small visual layout issue caused by editor selection placeholders, helping pages display more consistently.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
Fixed a rounding issue that could make a fully balanced trial balance appear to have a very small remaining amount when exported to Excel. This helps finance users trust that reports reflect zero balances correctly instead of showing confusing scientific-notation values.
Original PR description
Steps to reproduce -------------------- - Install account_reports module; - Create a new account; - Create a miscellanous operation for the previous month using thenew account with a credit amount of $8.28; - Create a second MISC for the current month with two lines using the account : debit = 262.67 and credit = 254.39; - Open the trial balance report and filter the new account (end balance should be 0); - Export the report as XLSX; The end balance value is 2.84e-14 due to float rounding issues. opw-6369016 Forward-Port-Of: odoo/enterprise#123896
The IVA Simple sales CSV now correctly fills the buyer subject type for customers marked as “IVA No Alcanzado” in Argentina. This prevents blank values in tax reporting exports and helps businesses submit more complete AFIP-compliant files.
Original PR description
### Description AFIP responsibility code `15` (IVA No Alcanzado) was missing from the `CASE WHEN` in `_vat_simple_build_sale_query`, so the "Tipo de sujeto comprador" (`responsibility_type_code`) column was left empty in the IVA Simple sale CSV for partners with that responsibility. This adds `15` to the exempt bucket (value `3`), next to its pair code `16` (IVA No Alcanzado - Otro), which was already handled there. ### Steps to reproduce 1. Set a partner's AFIP responsibility to "IVA No Alcanzado" (code 15). 2. Generate the IVA Simple sale CSV. 3. Before: the "Tipo de sujeto comprador" column is empty for that partner's rows. 4. After: it is reported as `3` (exempt bucket). Forward-Port-Of: odoo/enterprise#125007
This update corrects how Accounting Reports detects whether previously opened report sections exist. It helps ensure reports restore or handle open sections reliably instead of missing the empty-state condition.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**
Forward-Port-Of: odoo/enterprise#125258
Forward-Port-Of: odoo/enterprise#124223Planning kanban cards now move longer content onto the next line instead of squeezing it into a single row. This makes card details easier to read and prevents information from being cut off or displayed awkwardly.
Original PR description
Wrap the kanban card content onto the next line when it does not fit on a single line. task-5085363 Forward-Port-Of: odoo/enterprise#124816
This fix prevents Mexican payroll payslips from showing an error when a user clears the start or end date. The system now checks that dates are present before running salary-limit warning calculations, keeping payslip editing stable.
Original PR description
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI`…
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI` company - Go to `Payslips`, create a payslip. - Set an `employee`, and remove either the `start date` or the `end date` from Period.. `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` After the [recent commit] adding a warning about the employee exceeding the salary limit, when the user removes the dates from the payslip, the compute method attempts to compute the warning from [1], and when it adds relativedelta to date_from, which is False, it raises the error [2]. This commit ensures that the payslip dates are checked first before adding relativedelta to the date and performing the comparison. [recent commit]: https://github.com/odoo/enterprise/commit/6abfa47dafe439f9328d606ef6ac5126ec6eb1f6 [1]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/hr_payroll/models/hr_payslip.py#L1446 [2]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py#L272-L276 Forward-Port-Of: odoo/enterprise#122643
This fixes an error that could occur when a Knowledge article linked to an Annual Report was sent to trash and the automatic cleanup job ran. The cleanup now also removes the linked annual report record, preventing failed maintenance jobs and related system error reports.
Original PR description
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install…
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install ``accountant_knowledge`` module - Go to Accounting > Review > Annual Report > Create a new annual report - Go to Knowledge > Open the knowledge article linked to the annual report > Send to Trash - Run the ``Base: Auto-vacuum internal data`` cron Traceback: ```py ForeignKeyViolation: update or delete on table "knowledge_article" violates foreign key constraint "audit_report_knowledge_article_id_fkey" on table "audit_report" DETAIL: Key (id)=(67) is still referenced from table "audit_report". ``` https://github.com/odoo/enterprise/blob/04cce2e400ce2e412f28aa1849078a7c40ff0e2c/knowledge/models/knowledge_article.py#L1069-L1070 The garbage collector deletes trashed knowledge articles that match its domain. Since this domain also includes articles linked to Annual Reports, the cron attempts to delete records that are still referenced by annual report, resulting in a foreign key violation error. Solution: Ensure linked audit reports are also deleted during knowledge article garbage collection. sentry-7488793071 Forward-Port-Of: odoo/enterprise#121189
This fixes the French VAT report so the BA zone is sent using the expected free-text format instead of a numeric value. The change helps ensure generated VAT submissions match the required format and reduces the risk of filing errors.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id Forward-Port-Of: odoo/enterprise#125335
### Description of the issue/feature this PR addresses: - Opening Studio on a form containing a Many2many field using the many2many_tags_email widget crashes with an OWL prop validation error. - **Steps to reproduce:** 1. Open any form view (e.g., Contacts) and enter `Studio`. 2. Create a new `Many2many` custom field on a model such as `res.partner`. 3. Set the field's widget to `many2many_tags_email` and save the customization. 4. Exit Studio and populate the field with one or more
Original PR description
### Description of the issue/feature this PR addresses: - Opening Studio on a form containing a Many2many field using the many2many_tags_email widget crashes with an OWL prop validation error. -…
### Description of the issue/feature this PR addresses: - Opening Studio on a form containing a Many2many field using the many2many_tags_email widget crashes with an OWL prop validation error. - **Steps to reproduce:** 1. Open any form view (e.g., Contacts) and enter `Studio`. 2. Create a new `Many2many` custom field on a model such as `res.partner`. 3. Set the field's widget to `many2many_tags_email` and save the customization. 4. Exit Studio and populate the field with one or more related records. 5. Open Studio again on the same form view. This results in the following error: ```.js Error: Invalid props for component 'RecipientTag': 'onDelete' is undefined (should be a value) ``` ### Current behavior before PR: - When opening Studio on a form containing a `Many2many` field with the `many2many_tags_email` widget, the field is rendered with `onDelete` set to undefined by `Many2ManyTagsField`. Starting from `saas-19.1`, the `many2many_tags_email` widget uses the new [RecipientTag] component, which requires onDelete to be defined. As a result, Owl's prop validation fails when RecipientTag receives `onDelete = undefined`, causing Studio to crash with an I nvalid props for component 'RecipientTag' error. ### Desired behavior after PR is merged: - RecipientTag should allow onDelete to be optional so that it can also be used when the parent field does not provide a delete callback. This prevents the Owl prop validation error when opening Studio, while keeping the existing delete functionality unchanged for editable fields where onDelete is available. opw:6395209 [RecipientTag]: https://github.com/odoo/odoo/blob/saas-19.1/addons/mail/static/src/core/web/recipient_tag.js --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/c88086079f [REL] 19.1.29 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/e8dafa04d1 [FIX] autofill: hide autofill handler when selection is hidden [Task: 6317808](https://www.odoo.com/odoo/2328/tasks/6317808) https://github.com/odoo/o-spreadsheet/commit/33ef954e9f [FIX] HeaderVisibility: fix `getNextVisibleCellPosition` getter [Task: 6340589](https://www.odoo.com/odoo/
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/c88086079f [REL] 19.1.29 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/c88086079f [REL] 19.1.29 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/e8dafa04d1 [FIX] autofill: hide autofill handler when selection is hidden [Task: 6317808](https://www.odoo.com/odoo/2328/tasks/6317808) https://github.com/odoo/o-spreadsheet/commit/33ef954e9f [FIX] HeaderVisibility: fix `getNextVisibleCellPosition` getter [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/6340589) https://github.com/odoo/o-spreadsheet/commit/d262fe5e19 [FIX] edition: do not change edition if not editing [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/6340589) 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>
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False a
Original PR description
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False and because that `Vat` field became reaonly and after recent fix `is_commercial_address` was set from `can_edit_vat` and validation done based on `can_edit_vat` before that `Vat` was editable if they have confirmed documents Fix: - Only make `Vat` readonly if Vat is set and is not individual address
**Description of the issue/feature this PR addresses:** [FIX] account: prevent access error for branch users When a user restricted to a branch company opens the accounting dashboard, they may encounter an AccessError preventing the app from loading. This occurs because the dashboard logic attempts to read the `fiscalyear_lock_date` from the journal's company. In a branch setup, this configuration often belongs to the parent company, which the user typically does not have read acc
Original PR description
**Description of the issue/feature this PR addresses:** [FIX] account: prevent access error for branch users When a user restricted to a branch company opens the accounting dashboard, they may…
**Description of the issue/feature this PR addresses:** [FIX] account: prevent access error for branch users When a user restricted to a branch company opens the accounting dashboard, they may encounter an AccessError preventing the app from loading. This occurs because the dashboard logic attempts to read the `fiscalyear_lock_date` from the journal's company. In a branch setup, this configuration often belongs to the parent company, which the user typically does not have read access to. The system then blocks the action and gives an AccessError. This commit resolves the issue by adding `.sudo()` when reading the `fiscalyear_lock_date`. This safely bypasses the record rule restriction, allowing the dashboard to fetch the necessary accounting configuration without requiring the user to have broad access to the parent company. **Steps to reproduce:** - As Mitchell Admin: - Settings > Users & Companies > Companies > My Company (San Francisco) > Branches > create a branch - Settings > Users & Companies > Users > Marc Demo > Access Rights > change “Companies” and “Default Company” to only the newly created branch - As Marc Demo: - Attempt to access Accounting app > observe Access Error **Current behavior before PR:** - Users belonging to only a branch company are unable to access the Accounting dashboard **Desired behavior after PR is merged:** - Users belonging to only a branch company are able to access the Accounting dashboard opw-6369616
The footer slideout state was computed only once during interaction setup. If the main content height changed afterward, e.g. in edit mode: dropping or removing snippets, or resizing the window, the effect could remain enabled/disabled even though the content had become taller/shorter than the viewport. Steps to reproduce: - Go into edit mode - Add two snippets on the page - On the footer, set the "Slideout Effect" option to "Slide Hover" - Remove one snippet - Half of the footer is
Original PR description
The footer slideout state was computed only once during interaction setup. If the main content height changed afterward, e.g. in edit mode: dropping or removing snippets, or resizing the window, the effect could remain enabled/disabled even though the content had become taller/shorter than the viewport. Steps to reproduce: - Go into edit mode - Add two snippets on the page - On the footer, set the "Slideout Effect" option to "Slide Hover" - Remove one snippet - Half of the footer is hidden by the hover effect, which should not happen task-6117257 Forward-Port-Of: odoo/odoo#277614 Forward-Port-Of: odoo/odoo#275291
**Steps to reproduce:** * Install l10n_fr. * Create an invoice using a tax with the E3 tax grid. * Post the invoice so it is included in the tax report. * Open the French tax report. **Observed Behaviour:** The E3 line is blank even though the amount is present in the report data. The amount is recorded as a negative value, while the report formula expects a positive value, causing it to be deducted from the report total. **Cause:** The E3 tax report expression used the for
Original PR description
**Steps to reproduce:** * Install l10n_fr. * Create an invoice using a tax with the E3 tax grid. * Post the invoice so it is included in the tax report. * Open the French tax report. **Observed Behaviour:** The E3 line is blank even though the amount is present in the report data. The amount is recorded as a negative value, while the report formula expects a positive value, causing it to be deducted from the report total. **Cause:** The E3 tax report expression used the formula E3, which does not account for tax grid amounts stored as negative values. **Fix:** Update the E3 report expression formula from E3 to -E3 so that negative E3 amounts are correctly displayed in the tax report. opw - 6321790 Forward-Port-Of: odoo/odoo#274052
Before this commit, the res.users model was not being loaded in the POS when reloading data. If user A was logged in and then on the same device user B logged in, it would not load the new user B data, and it causes user B to not be able to go to the backend. opw-6388954 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276546
Original PR description
Before this commit, the res.users model was not being loaded in the POS when reloading data. If user A was logged in and then on the same device user B logged in, it would not load the new user B data, and it causes user B to not be able to go to the backend. opw-6388954 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276546
iOS devices currently display the first letter of the website name instead of a favicon when creating a shortcut. This commit adds the `apple-touch-icon` link tag referencing the favicon to ensure the icon displays correctly. This commit is a backport of [1], which was merged in master(saas-19.2). task-5427275 [1]: https://github.com/odoo/odoo/commit/2506fdfc49f1515aea7e715e9f6d66418a093401 Forward-Port-Of: odoo/odoo#277723
Original PR description
iOS devices currently display the first letter of the website name instead of a favicon when creating a shortcut. This commit adds the `apple-touch-icon` link tag referencing the favicon to ensure the icon displays correctly. This commit is a backport of [1], which was merged in master(saas-19.2). task-5427275 [1]: https://github.com/odoo/odoo/commit/2506fdfc49f1515aea7e715e9f6d66418a093401 Forward-Port-Of: odoo/odoo#277723
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment
Original PR description
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing…
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment created for the expense report - edit the memo or the journal and save, then try to edit the date Editing the date is refused with "You cannot do this modification since the payment is linked to an expense report", while the memo and journal changes are silently accepted. Solution: Restore the missing comma and protect the renamed memo field. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277737 Forward-Port-Of: odoo/odoo#277423
Steps to reproduce: - activate location - create a tracked product A - create a PO with qty=10 with product A - receive them (8 in WH/Stock, 2 in WH/Stock/Shelf 1) - In Reporting/stock filter with "wh/stock" Issue: On hand value will be 0 Cause: "wh/stock did not match _rec_names = 'name' -> WH location is different than "stock" location (who's parent is "WH"). We need to match it with _rec_names_search (1) to match the right location. We fall back on _rec_names in case _rec_name
Original PR description
Steps to reproduce: - activate location - create a tracked product A - create a PO with qty=10 with product A - receive them (8 in WH/Stock, 2 in WH/Stock/Shelf 1) - In Reporting/stock filter with "wh/stock" Issue: On hand value will be 0 Cause: "wh/stock did not match _rec_names = 'name' -> WH location is different than "stock" location (who's parent is "WH"). We need to match it with _rec_names_search (1) to match the right location. We fall back on _rec_names in case _rec_names_search would not be defined (not really necessary in here but meh why not be conservative) (1) https://github.com/odoo/odoo/blob/2bb7493b72b400ed76cc6460c94867fb86de9f3a/addons/stock/models/stock_location.py#L19 opw-6312702 Forward-Port-Of: odoo/odoo#271552
# How to reproduce - Enable Cloudflare Turnstile in Settings > Integrations - Add a CF Site Key & a CF Secret Key. e.g. : - `1x00000000000000000000AA` - `1x0000000000000000000000000000000AA` (See : https://developers.cloudflare.com/turnstile/troubleshooting/testing/) - Go to a Website page with a form - Add `?cf=show` to the URL - Open the browser console - Search the dom for an element with s_turnstile_container - Look for the `data-appearance` attribute # The issue `data-appea
Original PR description
# How to reproduce - Enable Cloudflare Turnstile in Settings > Integrations - Add a CF Site Key & a CF Secret Key. e.g. : - `1x00000000000000000000AA` - `1x0000000000000000000000000000000AA` (See :…
# How to reproduce - Enable Cloudflare Turnstile in Settings > Integrations - Add a CF Site Key & a CF Secret Key. e.g. : - `1x00000000000000000000AA` - `1x0000000000000000000000000000000AA` (See : https://developers.cloudflare.com/turnstile/troubleshooting/testing/) - Go to a Website page with a form - Add `?cf=show` to the URL - Open the browser console - Search the dom for an element with s_turnstile_container - Look for the `data-appearance` attribute # The issue `data-appearance` is set to `interaction-only` but should be `always` according to : https://github.com/odoo/odoo/blob/1e73172b51cd673c3414187af4f98304921ed7b3/addons/website_cf_turnstile/static/src/interactions/turnstile.js#L8-L12 # Cause `appearance` is misspelled in the template : https://github.com/odoo/odoo/blob/1e73172b51cd673c3414187af4f98304921ed7b3/addons/website_cf_turnstile/static/src/interactions/turnstile.xml#L7 Documentation on the Appearance modes for Turnstile : https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/widget-configurations/#appearance-modes opw-6359977 Forward-Port-Of: odoo/odoo#275077
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes
Original PR description
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes this by refactoring the assertions to treat the output HTML structure as a "black box", verifying data integrity and expected content conversions rather than brittle structural layout. runbot-938228 Forward-Port-Of: odoo/odoo#277747 Forward-Port-Of: odoo/odoo#275959
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the BOM's form view. 4) Configure the first sequential operation to be blocked by the second 5) Make and confirm an MO using this BOM 6) Uncheck "Operation Dependencies" on the BOM 7) Press "Plan" on the MO, a validation error is thrown stating "You cannot create cyclic dependency." Issue occur
Original PR description
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the…
Steps to produce: 1) Install Manufacturing & enable "Work Order Dependencies" in the settings 2) Make a new BOM with 2 operations 3) Check "Operation Dependencies" in the miscellaneous tab on the BOM's form view. 4) Configure the first sequential operation to be blocked by the second 5) Make and confirm an MO using this BOM 6) Uncheck "Operation Dependencies" on the BOM 7) Press "Plan" on the MO, a validation error is thrown stating "You cannot create cyclic dependency." Issue occurs because after the MO is confirmed the blocked_by_workorder_ids field for mrp.workorder records is set based on the order manually configured on the BOM (operation 1 is blocked by operation 2). After the BOM is edited to have allow_operation_dependencies = false, then Odoo uses the default sequential ordering when planning the operations (operation 2 is blocked by operation 1). Since the old ordering is never cleared, a cycle is created unintentionally. This PR resolves this issue by clearing the blocked_by_workorder_ids field on mrp.workorder records. opw-6334271 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275154
Firefox has a strict limit of ~640,000 characters for history state serialization and throws NS_ERROR_ILLEGAL_VALUE past it. Chrome and Safari throw DataCloneError past their own undocumented limits (~500MB and ~64MB respectively). When a debounced push() exceeded these limits, the error was unhandled and broke navigation. Catch these two specific errors and log them instead of crashing, while still resetting the push state and re-throwing any other unexpected error. opw-6182687 Forward-P
Original PR description
Firefox has a strict limit of ~640,000 characters for history state serialization and throws NS_ERROR_ILLEGAL_VALUE past it. Chrome and Safari throw DataCloneError past their own undocumented limits (~500MB and ~64MB respectively). When a debounced push() exceeded these limits, the error was unhandled and broke navigation. Catch these two specific errors and log them instead of crashing, while still resetting the push state and re-throwing any other unexpected error. opw-6182687 Forward-Port-Of: odoo/odoo#277724
Before this commit, when clicking on refresh and the kyc_status on IAP was 'fail', we put the status on the db to 'fail' and ended the process. This implies creating a new record IAP side even if it is useless and also implies that there could be cases where there would be a mismatch between iap and Odoo. e.g. The client starts a verification process, he ends up refusing to sign the documents. On IAP, the kyc status would be equal to 'fail'. Then the user have a possibility to submit a manual
Original PR description
Before this commit, when clicking on refresh and the kyc_status on IAP was 'fail', we put the status on the db to 'fail' and ended the process. This implies creating a new record IAP side even if it is useless and also implies that there could be cases where there would be a mismatch between iap and Odoo. e.g. The client starts a verification process, he ends up refusing to sign the documents. On IAP, the kyc status would be equal to 'fail'. Then the user have a possibility to submit a manual verification and when submitting it status would go to 'processing'. The problem is that in the meantime (after refusing but before submitting manual verification), if the user clicks on the refresh button it would ends the process on Odoo and then not going to 'success' on the DB even if it is the case on IAP after Support reviewed the request. task-6307255 Forward-Port-Of: odoo/odoo#277045 Forward-Port-Of: odoo/odoo#276191
hash_sign has become very used all over the place, so more and more tokens depend on `database.secret`, increasing the impact of that secret needing one day to be rotated or being compromised. To avoid making `database.secret` a single point of failure, we would like `hash_sign` to support a custom secret supplied by caller. task-6391264 Forward-Port-Of: odoo/odoo#276698 Forward-Port-Of: odoo/odoo#276474
Original PR description
hash_sign has become very used all over the place, so more and more tokens depend on `database.secret`, increasing the impact of that secret needing one day to be rotated or being compromised. To avoid making `database.secret` a single point of failure, we would like `hash_sign` to support a custom secret supplied by caller. task-6391264 Forward-Port-Of: odoo/odoo#276698 Forward-Port-Of: odoo/odoo#276474
## Problem When a `web_read_group` call is made with some condition on the active field, the active test is bypassed by adding `['active', 'in', [True, False]]` to the domain. This will cause a search to fail if the model's active field is not called `active` (like in a studio model). ## Solution We will change the domain to `[self._active_name, 'in', [True, False]]` to properly handle customizations. ## Steps to replicate (Runbot v19) 1. Create a new model with Studio - enable Pipeline
Original PR description
## Problem When a `web_read_group` call is made with some condition on the active field, the active test is bypassed by adding `['active', 'in', [True, False]]` to the domain. This will cause a search to fail if the model's active field is not called `active` (like in a studio model). ## Solution We will change the domain to `[self._active_name, 'in', [True, False]]` to properly handle customizations. ## Steps to replicate (Runbot v19) 1. Create a new model with Studio - enable Pipeline and Archiving 2. Open the kanban view and add 'Archived' to the filter 3. Traceback opw-6403422 Forward-Port-Of: odoo/odoo#277666
When creating an activity in a custom app made with studio, no image is shown, and instead the alt text is shown with a missing image. This fixes the issue by showing a placeholder icon if no module is found for the activity group. opw-6282451 Previous behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attachments/assets/1e4fc1d5-3a35-4193-80fc-f6d161776e2e" /> New behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attac
Original PR description
When creating an activity in a custom app made with studio, no image is shown, and instead the alt text is shown with a missing image. This fixes the issue by showing a placeholder icon if no module is found for the activity group. opw-6282451 Previous behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attachments/assets/1e4fc1d5-3a35-4193-80fc-f6d161776e2e" /> New behavior: <img width="1315" height="568" alt="image" src="https://github.com/user-attachments/assets/6ed5ca8b-8481-470f-b7c6-dd59c616125e" /> (Original PR: https://github.com/odoo/odoo/pull/268957 Re-based on 17.0 as its the earliest version affected, so it can be forward-ported to future versions) Forward-Port-Of: odoo/odoo#269654
# Problem Cost of production in the inventory valuation report does not respect 'As of' date, and will show current costs of production regardless of the specified date. # Solution `_get_report_data` in `mrp_account` is just missing the date enforcement when calling `_get_location_valuation_vals`, so we will simply pass this in. # Steps to reproduce (runbot v19) - FIFO Perpetual component with non-zero value - Manufactured product that consumes the above component 1. Set a cost of pro
Original PR description
# Problem Cost of production in the inventory valuation report does not respect 'As of' date, and will show current costs of production regardless of the specified date. # Solution `_get_report_data` in `mrp_account` is just missing the date enforcement when calling `_get_location_valuation_vals`, so we will simply pass this in. # Steps to reproduce (runbot v19) - FIFO Perpetual component with non-zero value - Manufactured product that consumes the above component 1. Set a cost of production account on the production location 2. Create and confirm an MO for the manufactured product 3. Go to Accounting > Review > Inventory Valuation, and set the At Date to something far in the past, befroe any move history in the db. Note the Cost of Production accounts have data that does not apply to this period opw-6229088 Forward-Port-Of: odoo/odoo#269911
1 change
Resolved issues and error corrections
The Trial Balance report now avoids tiny rounding artifacts when exporting to Excel, so balances that should be zero appear as zero. This improves report accuracy and prevents confusion when reviewing account balances.
Original PR description
Steps to reproduce -------------------- - Install account_reports module; - Create a new account; - Create a miscellanous operation for the previous month using thenew account with a credit amount of $8.28; - Create a second MISC for the current month with two lines using the account : debit = 262.67 and credit = 254.39; - Open the trial balance report and filter the new account (end balance should be 0); - Export the report as XLSX; The end balance value is 2.84e-14 due to float rounding issues. opw-6369016 Forward-Port-Of: odoo/enterprise#123896
6 changes
Resolved issues and error corrections
Opening the Scrap action from a new manufacturing operation in the Barcode app no longer crashes when no location or record is available yet. This keeps manufacturing barcode workflows usable and also avoids a related crash when scanning products with consignment enabled.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Open Barcode app; 2. click Operations; 3. click MANUFACTURING 4. click New; 5. click cogwheel on top right; 6. click Scrap. Issue ----- Traceback: > Error: Record stock.location with id=undefined doesn't exist in the cache Cause ----- When setting up the default context for the scrap menu, it it assumes `this.record` is not empty. Solution -------- Make `cache.getRecord` not raise an error when a location isn't found. Use optional chaining for other parts of the context that rely on a `record` being present. Also fixes a related issue introduced by 4b457fe, where the same traceback would be thrown on opening a new MO and scanning a product whilst consignment is enabled. opw-6397774 Forward-Port-Of: odoo/enterprise#124818
This fix makes an automated barcode transfer test wait until the transfer is truly ready before validating it. It reduces random test failures, helping keep stock barcode updates more stable and reliable.
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#125005
#### Description of the issue this PR addresses: - Blockquotes currently display their border on the left side. #### Desired behavior after PR is merged: - Update the styling so the border is displayed on the right side for RTL content. task-6296519 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269529
Original PR description
#### Description of the issue this PR addresses: - Blockquotes currently display their border on the left side. #### Desired behavior after PR is merged: - Update the styling so the border is displayed on the right side for RTL content. task-6296519 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269529
**Steps to reproduce:** - Create two companies - Create aliases for each company - Receive a bounced email on the alias of the second company - Recipient of the bounce email will be from the first company **Issue:** `self.env.company` is used in `message_route` for catchall mails without checking if it corresponds to the received domain, making it defaults to the 'main' company instead. **Fix:** Try to find the company of the given mail address using the `'mail.alias.domain'` and app
Original PR description
**Steps to reproduce:** - Create two companies - Create aliases for each company - Receive a bounced email on the alias of the second company - Recipient of the bounce email will be from the first company **Issue:** `self.env.company` is used in `message_route` for catchall mails without checking if it corresponds to the received domain, making it defaults to the 'main' company instead. **Fix:** Try to find the company of the given mail address using the `'mail.alias.domain'` and apply it on the body rendering and `_routing_create_bounce_email` function. similar fix in `account` module: https://github.com/odoo/odoo/commit/b7e0d8914d35af12a96593e484889e48c0613078 opw-5180433 Forward-Port-Of: odoo/odoo#244296
Before this commit, the default einvoice format was changed only when the partner was french and had a vat number, but we want to ease that condition and do it only if the partner is french. task-6303174 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270720
Original PR description
Before this commit, the default einvoice format was changed only when the partner was french and had a vat number, but we want to ease that condition and do it only if the partner is french. task-6303174 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270720
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO,
Original PR description
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get…
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO, click on "Bill matching" button - Select the 4 lines and click on the "Match" button -> On the purchase order, first line has qty_invoiced == 2 and the second one 0 -> On the bill, there is an additional line with 0 quantity This is because we only match the first order line in case of having more than one line with the same product. Then we add the remaining order lines to the bill. With this commit we match each line that need to be matched and we add lines to the bill only if all order lines have been invoiced. opw-6279755 Forward-Port-Of: odoo/odoo#269496
20 changes
Resolved issues and error corrections
This update standardizes how Odoo decides whether a database save can happen during key accounting, localization, and social workflows. It helps prevent unintended saves during tests or sensitive actions such as bank statement imports, reducing the risk of inconsistent results or failed processes.
Original PR description
…flag The aim of this commit is to allow forbidding a commit in specific condition and uniformize the way we check if a commit can be done. Context: There are a few places where checking the module.current_test flag isn't enough. For example, some test monkey patch it for specific reason and some business flow like the import of a csv of bank statement can't afford a commit. task-id: None
This fix moves the express mention to the correct section of the French VAT report file sent to Aspone. It helps ensure submitted VAT declarations follow the expected format and are less likely to be rejected or mishandled.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#124471 Forward-Port-Of: odoo/enterprise#123235
When a spreadsheet cannot be opened because its underlying model fails to load, Odoo now stops the follow-up synchronization step that depended on that missing data. Users still receive the intended error notification, but avoid an additional technical crash message.
Original PR description
Current behavior before PR: - In 4204ceb, model creation errors were caught and a notification was shown to the user. - However, syncSheetFromRouter() was still called afterward. Since it relies on model getters, it raise a traceback when no model existed. Desired behavior after PR is merged: - Call syncSheetFromRouter() only after the model has been created successfully. - This prevents accessing model getters when model creation fails and avoids the resulting traceback. Task: [6355245](https://www.odoo.com/odoo/project/2328/tasks/6355245) Forward-Port-Of: odoo/enterprise#124961 Forward-Port-Of: odoo/enterprise#122650
The appointment link copy confirmation now appears only after the copy action has actually been attempted. This prevents automated appointment CRM flows from moving ahead too early, making related tests and user interactions more reliable.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004 Forward-Port-Of: odoo/enterprise#124439
Odoo now places certificates from emSigner correctly in signed PDF documents after recent changes on the emSigner side. This prevents visibly misaligned certificates and helps keep signed documents professional and readable.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
Businesses can once again add comments when submitting Belgian VAT return XML files. This restores a previously available option that had been removed by mistake, helping teams include required context with filings.
Original PR description
This feature had been mistakenly removed. Forward-Port-Of: odoo/enterprise#124865
Shop Floor now places manufacturing orders with scheduled work ahead of orders that have no planned start time. This makes the work center view match the standard work order list and helps teams focus on jobs that are ready to proceed.
Original PR description
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will…
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will update the sorting logic in the MrpDisplay component to more gracefully handle falsy date_start values, sorting them to the end. ## Steps to reproduce (runbot 19) 1. Create 2 MOs with an operation (work order) involving a work center, we'll call them A and B. 2. Open Shop Floor and open the work center that the MOs' work orders belong to, and note they are ordered A, B (this is fine, neither are planned so the precedence falls back to id 3. Go back to MO B and plan it. This should give it precedence in Shop Floor 4. Under the work center in Shop Floor, note that the MOs are still ordered A, B, despite B's work order having a start date and A's work order not having one To further motivate this being unintended, you can go to Manufacturing > Operations > Work Orders, and you'll see MO B's work order sitting at the top of the list. opw-6303323 Forward-Port-Of: odoo/enterprise#123983 Forward-Port-Of: odoo/enterprise#121693
This fix keeps embedded views aligned correctly when they appear at the top of a Knowledge article. It prevents a visual spacing issue caused by editor selection placeholders, preserving the intended layout for users editing Knowledge content.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
This fix prevents the report editor from continuing to run after its display frame has been removed. It reduces crashes and test failures during report preview or editing, making the Studio report editing experience more reliable.
Original PR description
In the ReportEditorIframe component, the iframe may be removed at some point, to be replaced by another one. The problem is that the editor is destroyed only when the new iframe is loaded, so there…
In the ReportEditorIframe component, the iframe may be removed at some point, to be replaced by another one. The problem is that the editor is destroyed only when the new iframe is loaded, so there is a period of time in which the previous editor is alive, but the iframe is destroyed. It can causes issues with plugins, which assumes that we have a valid editable zone. For example, here is a common traceback:
test_print_preview (odoo.addons.web_studio.tests.test_report_editor.TestReportEditorUIUnit.test_print_preview)
Error received after termination: TypeError: Cannot read properties of null (reading 'getComputedStyle')
at http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16264:290
at Array.filter (<anonymous>)
at ToolbarPlugin.getFilteredTargetedNodes (http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16264:201)
at ToolbarPlugin._updateToolbar (http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16259:83)
at http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:5325:117
The fix is to subscibe to the removal of the iframe, and destroy immediately the editor.Shopee order lines now show the SKU for the specific product variant instead of the general product template when variants are used. This makes order details clearer for sales and fulfillment teams and reduces confusion when reviewing Shopee orders.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124428 Forward-Port-Of: odoo/enterprise#124031
This fixes how the point-of-sale barcode lookup feature checks whether a user may create new products. The permission is now evaluated immediately and consistently, helping avoid incorrect product creation options appearing during POS workflows.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125237 Forward-Port-Of: odoo/enterprise#123073
AI tool failures caused by invalid automated inputs are now logged without long error tracebacks, reducing noise in system logs. Detailed traceback information remains available in debug logs for teams that need to investigate issues.
Original PR description
Tool failures from bad LLM arguments were logged at ERROR level with a full traceback, polluting the logs. I have changed the logger to log error not exception so we get rid of the traceback error added another debug logger to show the traceback also task-6250418 Forward-Port-Of: odoo/enterprise#124241 Forward-Port-Of: odoo/enterprise#120281
The asset Related Entries button is now labeled Related Items and opens directly as a list instead of leading users into an unhelpful journal item form. This makes reviewing the accounting items linked to an asset simpler and less confusing.
Original PR description
If you create an asset and confirm it, you can see the Related Entries using the smart button Related Entries. The list view that opens is clickable, but it opens a quite useless form view of the Journal Items. - Rename breadcrumb button to Related Items - Make it behave like action_account_moves_all, to not open form view Ticket: [6385260](https://www.odoo.com/odoo/project/967/tasks/6385260) Forward-Port-Of: odoo/enterprise#124672
This fixes an issue where companies using the Peru localization could be blocked from creating certificates when the Chile localization was also installed. The Chile-specific serial number requirement now applies only where appropriate, preventing unnecessary setup errors for other Latin American localizations.
Original PR description
With a l10n_pe company and having a l10n_cl company installed: - Try to create a certificate in the settings, there is a missing field error. The template certificate_certificate_view_form have a required subject_serial_number field in l10n_cl but it shouldn't in other latam localization. opw-6274126 Forward-Port-Of: odoo/enterprise#120211
The draft button in Uruguay electronic invoicing now returns a valid response when called remotely. This prevents an error that could interrupt users or integrations when resetting an invoice to draft.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#125285 Forward-Port-Of: odoo/enterprise#124653
Automated barcode tests for scrap operations were adjusted so entered quantities are kept correctly during screen updates. This reduces random test failures and helps keep inventory and manufacturing barcode workflows stable.
Original PR description
These barcode scrap tours randomly trigger "You can only enter positive quantities." on runbot: the quantity set with a raw input.value is dropped when the field re-renders before the scrap is saved, so it scraps 0. Dispatching an input event keeps the typed value. error-238911 Forward-Port-Of: odoo/enterprise#124952
This fixes how the French VAT report fills the BA zone so it uses the required free-text field format instead of a numeric value. The change helps ensure generated VAT reports comply with the expected French reporting structure and reduces filing errors.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id Forward-Port-Of: odoo/enterprise#125335
The timesheet percentage now stays current as users add, edit, or remove timesheet entries. This avoids confusion from outdated percentages remaining visible until the page is reloaded.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186 Forward-Port-Of: odoo/enterprise#125312 Forward-Port-Of: odoo/enterprise#125074
Users can now rename Studio fields with labels written in Arabic or other non-Latin scripts without triggering an invalid field name error. This prevents a confusing failure when creating or editing fields for multilingual users, while keeping the existing technical field name when a safe new one cannot be generated.
Original PR description
Steps: - Install web_studio - Add any field (example char field) to any view - Rename it in arabic, example `السَّلَامُ عَلَيْكُمْ` - Error Custom field names cannot contain double underscores Webclient (view_editor_model) escape every non-alphabetic chars, so new label value contains nothing but a space which will be replaced by a _ this new label value will be concatenated to `x_studio_`. Resulting to the string `x_studio__`. A solution should be to prevent changing the technical name if the new label value (escaped) is empty. opw-6311027 Forward-Port-Of: odoo/enterprise#125299 Forward-Port-Of: odoo/enterprise#121343
The My Planning calendar now visually marks draft planning entries with the expected hatched style. This helps users quickly distinguish draft plans from confirmed ones and reduces confusion when reviewing schedules.
Original PR description
Issue: Calendar entries appear plain even when they should appear hatched. (ex. while in draft status) Steps to reproduce: If you create any planning and set it to draft. Then go to Planning > Planning > My Planning, the newly created plan should be in hatched but it becomes plain. Cause: In the view planning.slot.my.calendar there was missing the element that causes the views to become hatched when in draft status. Solution: Added said element. opw-6260055 Forward-Port-Of: odoo/enterprise#119153
4 changes
Resolved issues and error corrections
Manually printed confirmed payslips now save the generated PDF to the payslip record, matching the automatic send flow. This helps payroll teams keep a complete document history in the employee payslip chatter without extra manual uploads.
Original PR description
Right now, manually printing a confirmed payslip from the list view downloads the pdf but never links it to the chatter, unlike the automatic generate and send flow. This backports the fix from the odoo/enterprise#94019 pull request, making the print controller also create the attachment on the payslip. taskid-6391358
Fixed a rounding issue that could show a tiny leftover amount instead of zero in exported Trial Balance reports. This prevents confusion when accounts are actually balanced and improves the reliability of financial report exports.
Original PR description
Steps to reproduce -------------------- - Install account_reports module; - Create a new account; - Create a miscellanous operation for the previous month using thenew account with a credit amount of $8.28; - Create a second MISC for the current month with two lines using the account : debit = 262.67 and credit = 254.39; - Open the trial balance report and filter the new account (end balance should be 0); - Export the report as XLSX; The end balance value is 2.84e-14 due to float rounding issues. opw-6369016 Forward-Port-Of: odoo/enterprise#123896
The Stripe expense cardholder field has been corrected so it uses the standard selection behavior. This ensures filters set in the view are properly applied, helping users see only the relevant cardholders when entering expenses.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906
This fix prevents a test helper for appointment CRM flows from affecting later steps unexpectedly. It keeps automated validation more reliable, reducing false failures or hidden side effects in quality checks.
Original PR description
Capturing `oldWriteText` at module import and relying on a subsequent tour step to restore it can cause state leakage if the subsequent step doesn't exactly target a resulting effect of the mocked `writeText` call. Refactor the tour step to capture `writeText` dynamically and restore the original method on first call. runbot-241004
10 changes
Resolved issues and error corrections
Fixed an error that could appear when opening the Scrap action from a new manufacturing operation in the Barcode app. This improves reliability for warehouse and manufacturing users, including cases involving consignment stock scans.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Open Barcode app; 2. click Operations; 3. click MANUFACTURING 4. click New; 5. click cogwheel on top right; 6. click Scrap. Issue ----- Traceback: > Error: Record stock.location with id=undefined doesn't exist in the cache Cause ----- When setting up the default context for the scrap menu, it it assumes `this.record` is not empty. Solution -------- Make `cache.getRecord` not raise an error when a location isn't found. Use optional chaining for other parts of the context that rely on a `record` being present. Also fixes a related issue introduced by 4b457fe, where the same traceback would be thrown on opening a new MO and scanning a product whilst consignment is enabled. opw-6397774
**Description of the issue/feature this PR addresses:** [FIX] website_sale: preserve parent company link on address update When a portal user linked to a company (B2B) edits their address during website checkout, the backend partner form subsequently loses the visual link to their parent company and incorrectly displays a "Create company" button instead. This occurs because the checkout form submits the company name as a raw text string (`company_name`). This string gets passed in t
Original PR description
**Description of the issue/feature this PR addresses:** [FIX] website_sale: preserve parent company link on address update When a portal user linked to a company (B2B) edits their address during…
**Description of the issue/feature this PR addresses:**
[FIX] website_sale: preserve parent company link on address update
When a portal user linked to a company (B2B) edits their address during
website checkout, the backend partner form subsequently loses the visual
link to their parent company and incorrectly displays a "Create company"
button instead.
This occurs because the checkout form submits the company name as a raw
text string (`company_name`). This string gets passed in the payload and
is written to the contact's record. In the backend `res.partner` form
view, the presence of data in the `company_name` field triggers UI
modifiers that hide the `parent_id` relational field and switch to the
B2C company creation flow.
This commit resolves the issue by conditionally removing `company_name`
from the payload if the user already has a `parent_id`. This ensures the
raw text is safely ignored for B2B users, keeping the backend UI intact
while preserving the expected behavior for unlinked B2C users.
opw-6374326
**Steps to Reproduce:**
- Contacts > New
- Set type to “Company”, any name, any Tax ID
- (On same page) > Contacts & Addresses > Add
- Set type to “Contact”, set any name/email
- Access the previously created (individual) contact > settings/gear icon > grant portal access > Grant Access
- Access the (individual) contact user form > settings/gear icon > Change Password > (any)
- Log in as portal user > add item to cart > checkout > Modify address and save
- Access the created (individual) contact again
- Observe “Create company” button despite partner_id being set. In addition, the company name is shown correctly, but no link appears
**Current behavior before PR:**
- When a portal user linked to a company edits their address during website checkout, the backend partner form stores the company_name field and hides the link to the parent company while displaying a "Create company" button
**Desired behavior after PR is merged:**
- Portal users linked to a company should be able to edit their address without losing UI links to the parent company in the partner form### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/6a6cc73650 [REL] 18.0.76 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/5832d8abe3 [FIX] HeaderVisibility: fix `getNextVisibleCellPosition` getter [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/6340589) https://github.com/odoo/o-spreadsheet/commit/c93ad33981 [FIX] edition: do not change edition if not editing [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/6a6cc73650 [REL] 18.0.76 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/6a6cc73650 [REL] 18.0.76 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/5832d8abe3 [FIX] HeaderVisibility: fix `getNextVisibleCellPosition` getter [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/6340589) https://github.com/odoo/o-spreadsheet/commit/c93ad33981 [FIX] edition: do not change edition if not editing [Task: 6340589](https://www.odoo.com/odoo/2328/tasks/6340589) 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>
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Configure a multi-company environment with a `Main Company` and a `Secondary Company` - Go to the setting enable Lots & Serial Numbers and switch into `Secondary Company` - Create a warehouse for the Secondary Company - In the Secondary Company, create a lot-tracked storable product - Create and validate a delivery for that product - Open the Traceability Report - Print the report Is
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Configure a multi-company environment with a `Main Company` and a `Secondary Company` - Go to the setting…
Version:
--------
- 18.0+
Steps to reproduce:
-------------------
- Install `stock` module
- Configure a multi-company environment with a `Main Company`
and a `Secondary Company`
- Go to the setting enable Lots & Serial Numbers and switch into
`Secondary Company`
- Create a warehouse for the Secondary Company
- In the Secondary Company, create a lot-tracked storable product
- Create and validate a delivery for that product
- Open the Traceability Report
- Print the report
Issue:
------
The report header always displays the Main Company, even though the
traceability report belongs entirely to the Secondary Company.
Cause:
------
https://github.com/odoo/odoo/blob/2d54db3ac0b6d807e580315e2633f3e2b10a700c/addons/stock/static/src/client_actions/stock_traceability_report_backend.xml#L9
Clicking Print calls onClickPrint(), which builds the PDF URL and
downloads it with download() (a plain XMLHttpRequest POST), landing on
the `type='http'` route `/stock/<output_format>/<report_name>`
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L125-L134
That controller calls stock.traceability.report.get_pdf() without ever setting
`company_id` in the rendering context.
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/stock/controllers/main.py#L23
Inside `get_pdf()`, the report header is rendered by passing an `rcontext`
dict to `web.internal_layout`.
That template resolves the company to display using the following priority:
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/web/views/report_templates.xml#L805-L816
1. `company_id` — an explicit company record in the render context
2. `o.company_id` — the company of the document object `o`
3. `res_company` — the fallback, injected by `_render_template()` as
`self.env.company`
Because `get_pdf()` never sets `company_id` or `o` in `rcontext`, the
template always falls through to `res_company`.
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/odoo/addons/base/models/ir_actions_report.py#L770
This is populated by `ir.actions.report._render_template()`
as `self.env.company`, which resolves to the first company in
the user's `allowed_company_ids` list — typically the main company
regardless of which company owns the lot,
picking, or stock moves being printed.
As a result, the report content belongs to the secondary company while the
header always shows the main company.
Fix:
----
Resolve the company from the record on which the traceability report is
opened (using `active_model` and `active_id`) and pass it explicitly as
`company_id` when rendering the report.
`web.internal_layout` already gives precedence to an explicit
`company_id` over the default `res_company`, ensuring the report header
always displays the company that owns the traced record.
When the record has no company set, the header falls back to
`res_company`. Since the print request is a raw `type='http'` download
that never receives the company switcher's context, `user.context`
(holding `allowed_company_ids`) is now forwarded in the download POST
and merged into the environment by the controller - as done in
`web/controllers/report.py` - so the fallback resolves to the currently
active company instead of the user's default one.
<details>
<summary>Click here to see the results:</summary>
<p><strong>Before:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/7e3a5d65-9114-4bce-9139-a88cff7c261f" />
</div>
<p><strong>After:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/0a105f80-b6ae-400d-a787-fb8706d5f519" />
</div>
</details>
---
opw-6345446
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prCurrentyl the unsupported models will be checked like the following ```sql ia.res_model NOT IN ARRAY['model1', 'model2'] ``` This causes a syntax error. Use `ANY` to avoid the issue ```sql ia.res_model != ANY(ARRAY['model1', 'model2']) ``` Reproduce in Odoo shell ```python from odoo.tools import SQL query = SQL(""" SELECT ia.id FROM ir_attachment ia WHERE ia.res_model NOT IN %(unsupported_models)s LIMIT 1; """, unsupported_models=self.env['ir.atta
Original PR description
Currentyl the unsupported models will be checked like the following
```sql
ia.res_model NOT IN ARRAY['model1', 'model2']
```
This causes a syntax error. Use `ANY` to avoid the issue
```sql
ia.res_model != ANY(ARRAY['model1', 'model2'])
```
Reproduce in Odoo shell
```python
from odoo.tools import SQL
query = SQL("""
SELECT ia.id
FROM ir_attachment ia
WHERE ia.res_model NOT IN %(unsupported_models)s
LIMIT 1;
""",
unsupported_models=self.env['ir.attachment']._get_cloud_storage_unsupported_models(),
)
```
opw-6404861Issue: Compare to lot and serial number package are not multi company. It means that the package don't pass from a company to the other. So when a company deliver to another. The delivery will create a quant with the package. However the receipt in the other company will create a new quant without package (or a new package). It means that the quants are never reconcile and it could become difficult to understand what remains in intercompany location and what are artifact from past movements.
Original PR description
Issue: Compare to lot and serial number package are not multi company. It means that the package don't pass from a company to the other. So when a company deliver to another. The delivery will create a quant with the package. However the receipt in the other company will create a new quant without package (or a new package). It means that the quants are never reconcile and it could become difficult to understand what remains in intercompany location and what are artifact from past movements. In order to fix it, we introduce a new system parameter to directly unpack after the delivery. This way the receipt is always without source package and will automatically decrease the quant. opw-6376983
**STEP TO REPRODUCE** 1. Install l10n_fr_pdp and select the french company. 2. Go on a contact form, under invoicing, select 'by Approved Platform' for invoice sending. 3. Click on the eInvoice format selection, and notice the format 'France E-invoicing (UBL 2.1)' is not there. Note: with other invoice sending values, it shows up. **CAUSE** In the `_get_ubl_cii_formats_info()` override in `l10n_fr_pdp`, we declare the ubl_21_fr format as not being usable with the peppol invoice sending me
Original PR description
**STEP TO REPRODUCE** 1. Install l10n_fr_pdp and select the french company. 2. Go on a contact form, under invoicing, select 'by Approved Platform' for invoice sending. 3. Click on the eInvoice format selection, and notice the format 'France E-invoicing (UBL 2.1)' is not there. Note: with other invoice sending values, it shows up. **CAUSE** In the `_get_ubl_cii_formats_info()` override in `l10n_fr_pdp`, we declare the ubl_21_fr format as not being usable with the peppol invoice sending method. However, the Approved Platform invoice sending (used to send ubl_21_fr) *is* the peppol invoice sending method in disguise. (we reused the peppol invoice sending method because pdp and peppol are very similar). opw-6387796
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and c
Original PR description
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module…
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and confirm the invoice. - Try to `Send To Tax Agency`. **Error:** `Node: <Natura t-if="line.tax_ids.l10n_it_exempt_reason" t-out="line.tax_ids.l10n_it_exempt_reason"/>` `ValueError: Expected singleton: account.tax(102, 3)` **Root Cause:** At [1], the code accesses `line.tax_ids.l10n_it_exempt_reason`, but when an invoice contains multiple taxes, causing an error. **Fix:** This commit prevents the error and ensures the user can send a simplified invoice by applying a fix similar to [2]. [1]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_simplified_template.xml#L14 [2]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_template.xml#L28-L181 Ticket [link](https://www.odoo.com/odoo/project.task/6354138) Ticket [link](https://www.odoo.com/odoo/project.task/6379377) opw-6354138 opw-6379377 Forward-Port-Of: odoo/odoo#273823
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a
Original PR description
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which…
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a rounding line" and precision 1.00. - Make Company A the active company in the company switcher. - Set the cash rounding's profit and loss accounts to Company A accounts. - Switch the active company to Company B. - Set the cash rounding's profit and loss accounts to Company B accounts. - Make Company A the active company again, keeping both companies active. - Create a customer invoice for Company B. - Add one invoice line whose total is not a multiple of the rounding precision. - Set the invoice's cash rounding to the one above. > Adding the rounding line raises a cross-company UserError: the company-dependent account is resolved against Company A while the invoice belongs to Company B. Desired behavior after PR is merged: The rounding line resolves the company-dependent profit/loss account against the invoice's own company, so the rounding line always uses that company's account and no cross-company error is raised. Covered by the added test TestAccountMoveCashRoundingMultiCompany. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Helpers for the enterprise PR opw-5862529 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#270624
Original PR description
Helpers for the enterprise PR opw-5862529 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#270624
1 change
Resolved issues and error corrections
## Description When validating an invoiced order in PoS Restaurant, an intermittent `undefined: Backend Invoice` error can occur if the user validates the order before the draft synchronization has completed. This issue is difficult to reproduce consistently because it depends on network latency and the timing of user interactions. ### Steps to Reproduce 1. Open a PoS Restaurant session. 2. Add products to an order. 3. Click **Order** to start synchronizing the draft order. 4. Imm
Original PR description
## Description When validating an invoiced order in PoS Restaurant, an intermittent `undefined: Backend Invoice` error can occur if the user validates the order before the draft synchronization has…
## Description
When validating an invoiced order in PoS Restaurant, an intermittent `undefined: Backend Invoice` error can occur if the user validates the order before the draft synchronization has completed.
This issue is difficult to reproduce consistently because it depends on network latency and the timing of user interactions.
### Steps to Reproduce
1. Open a PoS Restaurant session.
2. Add products to an order.
3. Click **Order** to start synchronizing the draft order.
4. Immediately click **Payment**.
5. Enable **Invoice** (select a customer if needed).
6. Click **Validate** before the draft synchronization finishes.
7. Under slow or unstable network conditions, the payment validation may fail with:
```
undefined: Backend Invoice
```
## Root Cause
During payment validation, `_finalizeValidation()` calls `push_single_order()` to synchronize the current order before creating the invoice.
In PoS Restaurant, `sendDraftToServer()` synchronizes draft orders asynchronously without acquiring `pushOrderMutex`, while `push_single_order()` performs synchronization while holding the mutex. Although both methods share the `syncingOrders` set, they are not synchronized through the same locking mechanism, allowing them to race.
The race happens as follows:
1. `sendDraftToServer()` starts synchronizing the draft order and adds its ID to `syncingOrders`.
2. Before it finishes, the user clicks **Validate**.
3. `_finalizeValidation()` calls `push_single_order()`, which invokes `_save_to_server()`.
4. Since the order is already in `syncingOrders`, `_save_to_server()` skips it and returns an empty array (`[]`).
5. The existing code only checks `!syncOrderResult`. Since an empty array is truthy in JavaScript, execution continues.
6. `_finalizeValidation()` then accesses `syncOrderResult[0]?.account_move`, where `syncOrderResult[0]` is `undefined`, resulting in the `undefined: Backend Invoice` error.
## Fix
Check that the synchronization result is both defined **and non-empty** before accessing its first element.
### Before
```javascript
if (!syncOrderResult) {
return;
}
```
### After
```javascript
if (!syncOrderResult || !syncOrderResult.length) {
return;
}
```
If `push_single_order()` returns an empty array, `_finalizeValidation()` exits early instead of attempting to access `syncOrderResult[0]`, preventing the exception.
This patch does **not** remove the underlying race condition; it simply handles the empty synchronization result safely.
## Notes
* This issue only affects **17.0**, where synchronization relies on `createFromUi()`.
* In **18.0**, the synchronization flow was redesigned around `syncFromUi()` and local model updates, so this specific race condition no longer occurs.
## Reproduction Videos
The issue is timing-dependent and requires slow network conditions together with rapid user interactions. After multiple attempts, it was successfully reproduced several times on Runbot.
1. [Reproduction Attempt 1](https://drive.google.com/file/d/1-KmaTiCErwv_OsWxYdmCvRUSI9oY3FOF/view?usp=sharing)
2. [Reproduction Attempt 2](https://drive.google.com/file/d/1MSG57nhZXfrAv1wuEkRbsmLstW5Hk9jg/view?usp=sharing)
3. [Reproduction Attempt 3](https://drive.google.com/file/d/1fXdyfNKUgJLTrrDZTi_FXuCmupBL3x-f/view?usp=sharing)
opw-6367134