Monday, August 31, 2026
38 changes · master
Resolved issues and error corrections
Customers previewing helpdesk tickets can now see the Field service button when related interventions exist. This fixes a visibility issue caused by a portal display change, helping users access completed field service information as expected.
Original PR description
Steps to reproduce: -------------------------- 1. Install helpdesk_planning_field_service_sale_timesheet and website with demo data. 2. Open a helpdesk team (e.g., Customer Care) and enable field…
Steps to reproduce: -------------------------- 1. Install helpdesk_planning_field_service_sale_timesheet and website with demo data. 2. Open a helpdesk team (e.g., Customer Care) and enable field service planning. 3. Create a new ticket in Customer Care, plan two interventions, and mark them as completed. 4. Click the cog menu of the helpdesk ticket and click Preview. Issue: ------- The "Field service" button is not visible. Cause: ------- Earlier, portal card visibility and existence were controlled directly in the QWeb template. After the portal refactoring, their visibility and existence are now managed by `portal.entry` records. As a result, the field service entry is incorrectly considered unavailable, causing the test to fail on runbot. Related build: https://runbot.odoo.com/runbot/build/123497806 Fix: ------ Determine the visibility of the "Field service" portal entry using the corresponding `portal.entry` record. (Similar https://github.com/odoo-dev/odoo/commit/84ccbded9f4f1f00359b2eef59bce9527368fb05) Related pr: https://github.com/odoo/enterprise/pull/129227 opw-6481737 Forward-Port-Of: odoo/enterprise#129860
This fix prevents broad internal searches when security rules rely on document-related fields, avoiding cases where systems with many attachments could become unable to fetch product documents efficiently. It improves reliability and performance for databases with large numbers of attachments without changing user-facing workflows.
Original PR description
When the security domain uses a many2one field that needs the `search_domain` context, the field itself might not be present in the user-given domain. When this happens, we assumed to search on all records which is too much in the case of attachments. The practical example is product.document where a simple fetch could not be done anymore on databases having a lot of attachments. opw-6486492 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285146
Users can again create folders, links, and document requests in the Documents app without seeing an error. The fix restores the proper behavior after a recent internal code change, preventing interruptions in document organization workflows.
Original PR description
The recent JS refactoring in commit b0aeefd7a1e moved several logic hooks into class methods, but they lost their execution context when passed down as props to child components. Steps to reproduce: 1. Open the Documents app. 2. Try to create a new folder, URL, or document request from the UI. 3. Traceback appears: `TypeError: Cannot read properties of undefined`. This commit fixes the issue by binding the component's context to these callback methods during setup so they execute correctly. Task-6524435
Belgian payroll reporting now uses the correct DMFA remuneration code for benefits in kind when an employee has no working days on the payslip. This helps ensure payroll declarations comply with Belgian reporting rules and reduces the risk of incorrect submissions.
Original PR description
Previously, BIK remunerations were reported in the DMFA using code 1. This change uses remuneration code 2 for BIK in months where the employee has no working days on the payslip. task: 6431491
Belgian SODA file imports now work for users who do not have Analytic Accounting access when that feature is not enabled. This prevents an unnecessary access error and lets affected accounting users complete their import workflow normally.
Original PR description
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error even if Analytic Accounting is not…
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error even if Analytic Accounting is not enabled. This occurs because the import wizard reads the `analytic_account_id` field on the `soda.analytic.mapping` model to build an internal dictionary of departments. Because this field is restricted to the Analytic Accounting group, the evaluation of this field crashes the import for users even when the Analytic Accounting feature is disabled. This commit resolves the issue by using `.sudo()` on the analytic mapping recordset to bypass the field-level group restriction. **Steps to reproduce:** - Log in as Mitchell Admin, change company to “My Belgian Company” - Settings > Users & Companies > Users > Mitchell Admin > Access Rights > Extra Rights > ensure “Analytic Accounting” is unchecked - Also ensure Mitchell Admin is not part of the “Analytic Accounting” group - Accounting Dashboard > remove “Favorites” from filter > drag & drop a SODA XML file to “Miscellaneous Operations” > save > observe Access Error **Current behavior before PR:** - Users who don't belong to the Analytic Accounting group encounter an access error when attempting to import SODA XML files, even when the Analytic Accounting feature isn't enabled **Desired behavior after PR is merged:** - Those users no longer receive an access error opw-6376039 Forward-Port-Of: odoo/enterprise#127867
The Peruvian sales ledger now reports the full gross value of sales affected by the 3% IGV withholding. This aligns the report with SUNAT expectations and avoids understating sales totals because the withholding is handled as a payment-time mechanism.
Original PR description
The 3% IGV withholding is a negative sale tax, so it reduced amount_total and the 14.4 ledger reported a net total. SUNAT expects the gross total of the operation, the withholding being a payment-time mechanism. task-5935227 Forward-Port-Of: odoo/enterprise#129089 Forward-Port-Of: odoo/enterprise#128849
Belgian payroll now correctly applies an employee's default private fuel card use when calculating payslips, when applicable. The related fuel card private use amount is also categorized as a benefit in kind, helping ensure the right social security and withholding treatment.
Original PR description
FUEL_CARD_PRIV never fired: nothing copied the employee's fuel_card_personal_use default into the payslip's property input. Fixed by seeding it in _compute_input_line_ids(), gated on fuel_card set, no company car, no mobility budget. FUEL_CARD_PRIV is also a Benefit in Kind (ONSS + withholding), like ATN.INT, but was missing the BIK category. Added it. Task 6469003 Forward-Port-Of: odoo/enterprise#129581 Forward-Port-Of: odoo/enterprise#128789
This fix makes Odoo properly clean up reusable page elements such as popups, carousels, tooltips, menus, and tabs when users leave or refresh parts of a page. It reduces browser memory growth during repeated page interactions and automated testing, improving stability without changing normal user workflows.
The search bar now uses the same rounded styling in both Community and Enterprise editions, reducing visual inconsistencies for users. This also makes dashboard search bars match the rest of the interface and simplifies future maintenance and testing.
Original PR description
*: spreadsheet_dashboard The round styling of the search bar was defined in web_enterprise, as xpaths over web.SearchBar / web.SearchBarMenu plus two scss files, so community and enterprise had two visibly different search bars. There is not much reason for them to differ, so the enterprise look becomes the only one and is written directly on the base templates. It also removes two annoyances: hoot tests often load web without web_enterprise, so the actual styling inside tests moves even further away from reality, and xpath attribute edition always adds complexity to the code so it ends up less readable and harder to customize without issues. The dashboard search bar, a standalone template the xpaths never reached, is a good example of that so this commit also adapts its template to the unified styling.
When an action fails, Odoo now keeps existing dialogs open instead of closing them during recovery. This prevents users from losing important pop-ups or missing error-related dialogs, improving reliability in the web interface.
Original PR description
Before this commit, clicking a notification of an inaccessible record in the messaging menu opened no dialog, and the nightly build failed on FAILED: [4/8] Tour access_inbox_records_tour -> Step…
Before this commit, clicking a notification of an inaccessible record in the messaging menu opened no dialog, and the nightly build failed on
FAILED: [4/8] Tour access_inbox_records_tour -> Step .o_dialog
.o-mail-Message-body:text(Message in inaccessible record).
Element has not been found.
This happens because the messaging menu shows the message in a dialog from the rejected promise of the action, while the action service restores the controller displayed before the failure, and `_updateUI` closes every dialog at the end of a restore. A dialog the user had opened before the failed click is closed the same way.
This only shows since "[IMP] web, project: enable test_documents_full eslint" *: the group check that commit moves to the end of a cog menu `isDisplayed` ran on every view, and its await delayed the mount of the controller, so the stack was still empty when the error arrived and the error path restored nothing.
This commit fixes the issue by keeping the dialogs open when the restore recovers from a controller error, as such a restore brings back the controller that was already displayed.
https://runbot.odoo.com/odoo/error/946461
* https://github.com/odoo/odoo/pull/284082Point of Sale now ignores barcode scanner input when staff are entering refund quantities on the ticket screen. This prevents accidental refund amounts or confusing maximum-quantity warnings caused by scanned product barcodes.
Original PR description
Steps to reproduce: - Have a paid order with a product ordered once - Open the ticket screen, select that order and its line - Scan a product barcode with a keyboard-wedge scanner Issue: "Maximum…
Steps to reproduce: - Have a paid order with a product ordered once - Open the ticket screen, select that order and its line - Scan a product barcode with a keyboard-wedge scanner Issue: "Maximum Exceeded - The requested quantity to be refunded is higher than the ordered quantity. 6 is requested while only 1 can be refunded." When the line holds enough quantity no dialog is shown at all and a refund quantity taken from the barcode is silently set. Cause: A keyboard-wedge scanner types the barcode as a burst of keystrokes. The number buffer discards such bursts by waiting barcodeService.maxTimeBetweenKeysInMs before handling the keys it collected and dropping any batch of more than two, but only when its holder asks for it with `useWithBarcode`. TicketScreen never set the flag, so its buffer handled every keystroke on its own and the digits of the barcode reached _setToRefundDetail as the refund quantity. ProductScreen, OrderSummary and PaymentScreen all set it. Fix: Set `useWithBarcode: true` on the ticket screen number buffer. Since the keys are now handled with a delay, capture the buffer before the selected order or orderline changes, so that a keystroke is applied to the line that was selected when it was typed and not to the next one. opw-6465148 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285083 Forward-Port-Of: odoo/odoo#281962
Shop search results and filter counts now use the same product information when matching customer searches. This prevents irrelevant matches from hidden webpage formatting, improving result accuracy and performance for larger catalogs.
Original PR description
The `/shop` product results and facets use different search fields. In particular, facets search raw `website_description` HTML, causing terms such as `weight` to match CSS like `font-weight` and process far more products than are displayed. Use one shared field list for both paths: - `name` - `variants_default_code` - `description_sale` - `description_ecommerce` Stop searching `default_code`, internal `description`, and raw `website_description`. opw-6391984 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283238 Forward-Port-Of: odoo/odoo#280720
Opening the timesheet systray from a task now pre-fills the relevant project and task without resetting any running timer. This prevents users from losing tracked time unexpectedly and keeps timesheet entries accurate.
Original PR description
Before this commit, the prefill used when the user opens the timesheet systray when his current loaded page is a task, will alter the form view in the timesheet systray to set the project and task when those fields are unset. The problem is `unit_amount` is also given to 0 and so the timer is reset due to the prefill system. This commit makes sure the `unit_amount` field is not inside the prefill data to make sure the timer is no longer reset. opw-6481443 Forward-Port-Of: odoo/enterprise#128672 Forward-Port-Of: odoo/enterprise#128531
Self-order customers with a zero total no longer get sent to an unnecessary payment page. This makes checkout smoother for free items, fully discounted orders, or other no-payment scenarios.
Original PR description
Before this commit: -------- - Self-orders with a total amount of zero are still redirected to the payment page, which was unnecessary. After this commit: -------- - The payment step is now skipped for zero-amount self-orders, providing a smoother checkout flow. task-5106938 Forward-Port-Of: odoo/odoo#284736 Forward-Port-Of: odoo/odoo#230218
This fix makes navigation breadcrumbs visible again on portal list pages across several apps, including sales, purchases, projects, timesheets, accounting, loyalty, subcontracting, and partner assignment. Customers and portal users can more easily understand where they are and navigate back to the portal home area.
Original PR description
*=account, hr_timesheet, loyalty, mrp_subcontracting, project, purchase, sale, website_crm_partner_assign Steps to reproduce: 1. install sale 2. Create and confirm a sale order for a portal user 3.…
*=account, hr_timesheet, loyalty, mrp_subcontracting, project, purchase, sale, website_crm_partner_assign Steps to reproduce: 1. install sale 2. Create and confirm a sale order for a portal user 3. Login as a portal user 4. Open sale orders Issue: - Breadcrumbs are not visible beside the title. Cause: - After this commit https://github.com/odoo/odoo/commit/bba2fc505f5d0b4770eacc6877155b1aeda6d772 Variables are passed as attributes directly on the element, but breadcrumbs_searchbar was passed to portal_layout, but the nested portal_searchbar no longer received it. As a result, portal list pages rendered their title instead of the breadcrumb home link. Solution: - Pass breadcrumbs_searchbar directly to portal_searchbar Alternative: - An alternative would be to propagate t-call parameters to slot content in QWeb or changes the condition for breadcrumbs visibility related enterprise pr: https://github.com/odoo/enterprise/pull/118352 opw-6232899 Forward-Port-Of: odoo/odoo#266020
This fixes a display issue where default contact or user avatars could be downloaded instead of shown on screen in some environments. The generated avatar image format is now recognized consistently, so initials-based avatars appear properly across contacts, users, chatter, and Discuss.
Original PR description
**Description of the issue/feature this PR addresses:** `avatar.mixin._avatar_generate_svg()` generates an auto-initial SVG avatar for any record without a real uploaded image (used by `res.partner`,…
**Description of the issue/feature this PR addresses:** `avatar.mixin._avatar_generate_svg()` generates an auto-initial SVG avatar for any record without a real uploaded image (used by `res.partner`, `res.users`, and anything else inheriting `avatar.mixin`). The generated SVG opens with a single-quoted XML declaration: `<?xml version='1.0' encoding='UTF-8' ?>`. When this content is served via `/web/image/...`, `guess_mimetype()` needs to determine its Content-Type since it's a computed value with no stored attachment metadata. On systems where the installed `libmagic` library classifies that specific single-quoted byte pattern as `text/xml` rather than `image/svg+xml`, the wrong Content-Type reaches the browser. **Current behavior before PR:** On affected `libmagic` versions/databases, an auto-generated avatar (a contact or user with no uploaded photo) gets served with `Content-Type: application/octet-stream` (or `text/xml`) instead of `image/svg+xml`. Browsers can't render that inline as an image, so instead of showing the colored-initial avatar, the browser downloads it as an unrecognized file. This affects any place these avatars are displayed: contact/user form and kanban views, chatter message authors, Discuss, etc. Confirmed reproducible with `libmagic` 538 (`python-magic`), where the single-quoted declaration is classified as `text/xml`, while the exact same content with double-quoted attributes is correctly classified as `image/svg+xml`. **Desired behavior after PR is merged:** `_avatar_generate_svg()` now generates its markup with double-quoted attributes throughout, which is correctly sniffed as `image/svg+xml` regardless of the installed `libmagic` version. Auto-generated avatars render inline in the browser as intended. No other code depends on the exact quoting of this generated SVG - `res_users.py` and `hr_employee.py` both only assign the returned bytes to an image field without inspecting their content. Avatar fields are computed and non-stored, so nothing needs to be migrated - every record gets the corrected markup on its very next read, with no backfill required. Updated the two existing `test_avatar_mixin.py` tests that asserted the exact (single-quoted) SVG string, and added `test_generated_partner_avatar_mimetype` to assert the generated avatar is actually sniffed as `image/svg+xml`, so this can't silently regress. Ran locally: all 6 tests in `TestAvatarMixin` pass. Forward-Port-Of: odoo/odoo#285081 Forward-Port-Of: odoo/odoo#283149
This fixes portal pages so customers can once again see breadcrumb navigation next to page titles. The change improves navigation clarity across affected customer-facing areas such as appointments, helpdesk, subscriptions, field service, equity, and signing.
Original PR description
*=appointment, equity, helpdesk, planning_field_service, sale_subscription, sign Steps to reproduce: 1. install sale 2. Create and confirm a sale order for a portal user 3. Login as a portal user 4. Open sale orders Issue: - Breadcrumbs are not visible beside the title. Cause: - After this commit https://github.com/odoo/odoo/commit/bba2fc505f5d0b4770eacc6877155b1aeda6d772 Variables are passed as attributes directly on the element, but breadcrumbs_searchbar was passed to portal_layout, but the nested portal_searchbar no longer received it. As a result, portal list pages rendered their title instead of the breadcrumb home link. Solution: - Pass breadcrumbs_searchbar directly to portal_searchbar Alternative: - An alternative would be to propagate t-call parameters to slot content in QWeb or changes the condition for breadcrumbs visibility releted community pr: https://github.com/odoo/odoo/pull/266020 opw-6232899 Forward-Port-Of: odoo/enterprise#118352
This fix preserves the recorded cost of a tracked product lot after all items from that lot have been sold or consumed. This helps keep historical inventory valuation information accurate instead of showing a misleading zero cost.
Original PR description
Issue before this commit: ========================= When a lot-valuation-enabled product uses FIFO costing and all quantities from a lot are consumed, the lot's standard price is reset to 0. Steps to…
Issue before this commit: ========================= When a lot-valuation-enabled product uses FIFO costing and all quantities from a lot are consumed, the lot's standard price is reset to 0. Steps to Reproduce: ========================= - Install the stock_account and purchase modules. - Create a lot-tracked product and enable Valuation by Lot/Serial, set FIFO as the costing method. - Create a PO for 5 units of the product with a unit price of 5. - Receive the products and check the lot's standard price; it is set to 5. - Sell all the product quantity for that product. - Open the lot form. Observation: The lot's standard price (cost) is reset to 0. Cause of the issue: ========================= In this [PR](https://github.com/odoo/odoo/pull/276163), the FIFO valuation logic computes the standard price using: - std_price = value / quantity if quantity else 0 When the lot quantity becomes 0, the quantity used for this computation is also 0. As a result, the standard price is reset to 0 even though the lot's historical cost is still relevant. With This Commit: ========================= Keep the lot's standard price when its quantity reaches 0, instead of resetting it to 0.
Payslip totals for worked days and hours now count only paid work entries, so periods such as days outside an active contract no longer inflate totals. This gives payroll teams more accurate figures while still keeping unpaid lines visible for transparency.
Original PR description
### Purpose Fix totals (`sum_worked_days`, `sum_worked_hours`) on payslips by excluding unpaid worked days (e.g., "Out of Contract"). By updating the compute method for those fields to take account for `is_paid` lines only. Added a unit test to ensure mid-month contract totals calculate correctly. ### How to reproduce - Go to Payroll and create a contract for an employee starting in the middle of the month (e.g., 15th of the current month). - Generate a payslip for that employee for the full month. - Check the total "Worked Days" and "Worked Hours" at the top of the payslip. Before this PR: <img width="1238" height="516" alt="image" src="https://github.com/user-attachments/assets/76cfdb29-a706-481c-b07f-03aabc548e84" /> After this PR: <img width="1238" height="516" alt="image" src="https://github.com/user-attachments/assets/ca3e0ecd-fac3-4f98-b0bc-203aabb89c4b" /> task-6205747
This change rolls back a recent GIF resizing update because it caused slow performance and memory errors when pages displayed multiple GIFs. It helps keep image-heavy views, such as Kanban screens, responsive and reliable for users.
Original PR description
Revert commit d9fae40571c4f10c17fe00efc087cb25b30b85ab as it's slow on odoo.com and the call to `frame.copy()` is raising a MemoryError when loading a KanbanView with multiple gifs. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284884 Forward-Port-Of: odoo/odoo#284479
Point of Sale loyalty rewards now correctly grant a free product from a tagged product group when the cashier changes the quantity using the numpad or barcode quantities. This prevents missed promotions and ensures Buy 2 Take 1 offers behave consistently regardless of how items are entered.
Original PR description
Steps to reproduce: - create a "Buy 2 Take 1" program whose rule and reward both target a product tag containing several products - in the PoS, add one of the tagged products to the order - set its…
Steps to reproduce: - create a "Buy 2 Take 1" program whose rule and reward both target a product tag containing several products - in the PoS, add one of the tagged products to the order - set its quantity to 3 with the numpad Issue: The free product is not given. Clicking the product a third time instead of typing the quantity does give it, and so does a program whose reward is a single product. Cause: A reward whose products come from a tag is multi_product, so getClaimableRewards never computes its unclaimed quantity and the auto claim of updateRewards skips it: which product to give out is unknown. The only place claiming such a reward is addLineToCurrentOrder, which resolves it with the product that was just added. Setting a quantity does not go through it, hence the difference. Fix: Resolve the reward product the same way when auto claiming: the product of the line being worked on, or, failing that, the only reward product the order contains. The reward then follows the quantity of any of the tagged products, not only of the first one added, and the cashier is still asked when the order does not settle the choice. opw-6430385 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284777
Planning now calculates allocated hours correctly when multiple employees share the same shift and working schedule. This helps managers see accurate daily workload totals in the Gantt view, reducing scheduling mistakes.
Original PR description
## Steps to reproduce: - Install Planning and Employee - Create a working schedule for example 38h/week (8h,8h,8h,8h,6h) - Create two employees and assign the created working schedule to them -…
## Steps to reproduce: - Install Planning and Employee - Create a working schedule for example 38h/week (8h,8h,8h,8h,6h) - Create two employees and assign the created working schedule to them - Create a shift in planning for the two employees for a week - Notice in gantt view the total allocated hours for each day are not calculated correctly ## Cause: When calculating each cell's duration we fetch the resources' intervals while doing this here https://github.com/odoo/enterprise/blob/1851d3046682020686f517dec3c744d88a38b049/planning/static/src/views/planning_gantt/planning_gantt_renderer.js#L354-L359 we loop over the first interval and instead of pushing to the intervals we overwrite on the whole list with the interval we fetched so when it comes to the next interval it won't find any intersection so it will set the resourceIntervals to an empty array. So here https://github.com/odoo/enterprise/blob/1851d3046682020686f517dec3c744d88a38b049/planning/static/src/views/planning_gantt/planning_gantt_renderer.js#L231-L234 it will mess up the percentage calculation which will lead to wrong allocated hours numbers. ## Fix: Instead of overwriting on resourceIntervals we push to it the intervals returned to keep the intervals for each resource. opw-6316368 Forward-Port-Of: odoo/enterprise#123750
Corrects several SAF-T/FAIA report issues affecting Luxembourg audit exports, including negative tax amounts, software version length, foreign currency tax values, and invoice customer/supplier details. These fixes help businesses produce compliant audit files and reduce validation errors during tax reporting.
Original PR description
This is one of many errors fixing the FAIA report, which is the SAF-T report for Luxembourg. See PR #113316 for a list of similar PRs. ### Error 1: Negative tax amounts Auditors from Luxemborg…
This is one of many errors fixing the FAIA report, which is the SAF-T report for Luxembourg. See PR #113316 for a list of similar PRs. ### Error 1: Negative tax amounts Auditors from Luxemborg provided one Odoo user with analysis files of their FAIA xml report. The following discrepancy was present in more than 300 lines: `[TaxInformation/TaxAmount/Amount] # is negative. Only postive values are admitted. The sign is automatically determined by the corresponding CreditAmount (-) Or DebitAmount (+) on the same Line.` This discrepancy was caused by two different scenarios. The first was a negative `unit_price` line, such as a Discount product. The second was a tax with negative and positive repartition lines, such as a tax with xml ID `lu_2015_tax_AP-EC-17`. Luxembourg officials confirmed the following behavior: 1. The TaxInformation/TaxAmount/Amount element must be positive. 2. The TaxInformationTotals/TaxAmount/Amount element may be negative. 3. There may only be one TaxInformationTotals element per TaxCode in an Invoice element. This commit ensures that these conditions are met for the FAIA report. I'm not sure if the TaxInformation changes should also be applied to the base `account_saft saft_report.xml` file. ### Error 2: SoftwareVersion The SoftwareVersion element is limited to 18 characters. The relevant error from a customer's analysis file is below. Error: Value exceeds maxLength of "18". ### Error 3: CurrencyAmount The `account_saft` method `GeneralLedgerCustomHandler._saft_fill_report_tax_details_values()` does not report the amount of tax in foreign currency, instead replacing this value with the amount in company currency. No errors prompted this change; it just seems wrong on its face. ### Error 4: PR #113720 ensured that the TaxType element is always TVA. This means that the TaxType should no longer should be ignored in our example documents. ### Error 5: Schema validation failure The elements Inovice/CustomerInfo and Invoice/SupplierInfo are defined with the element `<xs:choice>` in the XSD file linked below. Only one can be present at any time, not both. https://pfi.public.lu/dam-assets/backup/FAIA/FAIA/XSD_Files.zip. note: currently the link is broken. PR #100749 allowed many parts of SAF-T code to display both customer and supplier data, including these elements. This commit ensures that the elements are mutually exclusive. opw-6344914 [Link](https://www.odoo.com/odoo/project.task/6344914) Forward-Port-Of: odoo/enterprise#129043 Forward-Port-Of: odoo/enterprise#126121
Manufacturing orders in warehouses using a 3-step production flow are now counted correctly in stock forecasts. This helps replenishment teams see incoming finished goods accurately and avoid unnecessary purchasing or production decisions.
Original PR description
### Steps to reproduce: - In the settings enable Multi-Steps Routes - Put your warehouse in manufacture in 3 steps - Create a storable product P - Create and confirm an MO for 1 unit of P - Go to…
### Steps to reproduce: - In the settings enable Multi-Steps Routes - Put your warehouse in manufacture in 3 steps - Create a storable product P - Create and confirm an MO for 1 unit of P - Go to Inventory > Operations > Procurement > Replenishment - Create a new one for P in WH/stock #### > The forecasted quantity in stock is still 0 but should be at 1 ### Cause of the issue: This is the exact use case already fixed in 85dd3369ed17b98b2ce485be04f140cf4cfa8aa3, which stamped the finished move with a `location_final_id` pointing at WH/Stock so that the move contributes to the forecast there even though its `location_dest_id` is the intermediate WH/Post-Production. That fix was reverted in practice by 42275f83dc5350822a625e19d65148e8b41ab1d4, which replaced the value with `mo.location_dest_id`: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/mrp/models/stock_move.py#L466-L467 Its reasoning was that in a single-warehouse setup `location_dest_id` equals the warehouse stock location, so the behaviour would be unchanged. That holds in 1 and 2 steps, where the extra step is on the component side and only moves `default_location_src_id` to the pre-production location. It breaks in 3 steps, the only mode that also moves `default_location_dest_id`, to the post-production location: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/mrp/models/stock_warehouse.py#L246-L247 and `_compute_locations` propagates it to the MO: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/mrp/models/mrp_production.py#L334-L341 WH/Post-Production is a sibling of WH/Stock under the warehouse view location, not a child of it. Since `location_final_id` takes precedence over `location_dest_id` for the non-done part of the move chain: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/stock/models/product.py#L331-L334 the finished move stopped being counted in the WH/Stock forecast. Why the test did not catch it: `test_3_steps_manufacturing_forecast` stayed green through the whole regression, because it scoped `virtual_available` with a `location_id` context key. `_get_domain_locations` only reads `location` and `warehouse_id`; `location_id` is silently ignored: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/stock/models/product.py#L284-L287 The call therefore fell through to the branch scoping the forecast to every warehouse view location: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/stock/models/product.py#L303-L309 and the warehouse view location is the common parent of both WH/Stock and WH/Post-Production. The assertion held regardless of where `location_final_id` pointed, so the test was a false positive from the start: it also passes with 85dd3369ed17b98b2ce485be04f140cf4cfa8aa3 fully reverted. Using the `location` key makes it fail without the fix and pass with it. ### Fix: Neither fix proposition was right on its own; each one was correct only in its own scenario. The`mo.warehouse_id.lot_stock_id` resolves the warehouse from the components, so it points at the wrong warehouse as soon as the finished product is produced for another one. `mo.location_dest_id` is the post-production location as soon as the warehouse manufactures in 3 steps, so it drops the quantity from the forecast of the manufacturing warehouse itself. What separates the two is not the warehouse but whether the destination is a transit step. In 3 steps the finished product only reaches the stock through the post-production push rule: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/mrp/models/stock_warehouse.py#L57 so the final location is the stock of the warehouse owning that destination. Any other destination is already final and is kept as is, which leaves cross-warehouse MOs and destinations set to a sub-location of the stock untouched. The rule's destination is read rather than `warehouse.lot_stock_id` because a push move takes its destination from the rule and not from the operation type: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/stock/models/stock_rule.py#L256-L260 so the forecast stays correct when the store step is reconfigured to land somewhere else than the warehouse stock. The rule is looked up on `pbm_route_id` by its `picking_type_id` instead of through `warehouse.sam_rule_id`, because that field is no longer set. It used to be an entry of `_generate_global_route_rules_values`, and it is that entry which made the generic warehouse machinery create the rule and store it back on the warehouse: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/stock/models/stock_warehouse.py#L403-L410 11e69870db1c49d9a6af79ffd263e4e162b34b6b removed it when the post-production step stopped being a pull rule on the Manufacture route and became a push rule generated from `get_rules_dict`. Only the field declaration was left behind, and nothing writes it any more: https://github.com/odoo/odoo/blob/6a56908e5febfdb4e6e0eacfb8655b092319819f/addons/mrp/models/stock_warehouse.py#L21-L22 so reading it would silently give an empty recordset. The lookup is not delegated to `_get_push_rule` to avoid a search per finished move. opw-4882390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285185 Forward-Port-Of: odoo/odoo#283234
This fix ensures user group checks work correctly when the same group is referenced by more than one XML identifier. It prevents access or permission checks from returning inconsistent results depending on which valid group identifier is used.
Original PR description
A group can be identified by multiple xmlids. We add support to provide a list of "refs" to the `SetDefintions` object.
Reproductible issue:
```
demo = self.env["res.users"].browse(5)
demo.has_group("accountant.group_account_user") # False
demo.has_group("account.group_account_user") # True
assert self.env.ref("accountant.group_account_user") == self.env.ref("account.group_account_user")
```
task-6471260
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285153
Forward-Port-Of: odoo/odoo#284866Changing a project’s visibility no longer fails when the project’s document folder includes shortcuts. This ensures access settings can be updated as expected while still preventing direct access changes on shortcut-only documents.
Original PR description
Changing a project's visibility fails when its documents folder contains a shortcut. The visibility change is never applied and the following error is raised: "You can not update the access of a…
Changing a project's visibility fails when its documents folder contains a shortcut. The visibility change is never applied and the following error is raised: "You can not update the access of a shortcut, update its target instead." ### Reproduction steps - Create a project and add a document to its folder. - Create another document outside the project's folder. - Create a shortcut to that document in the project's folder. - Change the project's visibility. ### Cause Changing a project's visibility updates the access rights of its folder and documents together. The shortcut access check is meant to reject operations performed only on shortcuts. However, reading `shortcut_document_id` on a recordset returns the shortcut targets found across that recordset. Therefore, the presence of a single shortcut makes the check reject the whole operation. This prevents regular documents and the project folder from having their access updated. ### Fix Only reject access updates when all records involved are shortcuts. This preserves the protection against changing shortcut access directly while allowing project access updates to include shortcuts alongside regular documents and folders. opw-6472637 Forward-Port-Of: odoo/enterprise#129588 Forward-Port-Of: odoo/enterprise#128756
Inventory users can now validate dropship transfers for products using average costing when landed costs are enabled. This prevents an access error that blocked normal sales and purchasing workflows for affected products.
Original PR description
# How to reproduce - Activate the stock_landed_costs module - Enable Dropshipping - Create a product with : - Category : - Costing Method : AVCO - Inventory Valuation : Perpetual - Routes : Dropship…
# How to reproduce - Activate the stock_landed_costs module - Enable Dropshipping - Create a product with : - Category : - Costing Method : AVCO - Inventory Valuation : Perpetual - Routes : Dropship - Atleast one vendor - Create a SO for that product - Confirm the SO & then Confirm the associated PO - Login as an user with "User" rights for Inventory - Try to validate the Dropship transfer # The issue You get an access error. If the same flow is done with a product with a Standard Price costing method, then the Dropship is properly validated # Cause When validating the Dropship, we'll call `_action_done` on the moves. This will trigger an update of the standard price of the product : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/stock_move.py#L177 https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/stock_move.py#L345-L349 Since we're in avco, this will run the `_run_average_batch` method : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/product.py#L675 That will fetch the value of each moves. For the Dropship moves, it'll do so by calling the `_get_value()` method : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/product.py#L486 This method will compute the value of the move, notably by using the associated landed costs : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/stock_move.py#L431 https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_landed_costs/models/stock_move.py#L14 Now the issue is that this computation calls `_read_group` on 'stock.valuation.adjustment.lines' that are retricted to inventory administrators : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_landed_costs/models/stock_move.py#L11 https://github.com/odoo/odoo/blob/5f6fb63d5d7585805642c702d096b2f882e73761/addons/stock_landed_costs/security/ir.model.access.csv#L4 # Proposed solution Get the value of the move in sudo like previously done in the flow : https://github.com/odoo/odoo/blob/60bc7ae38e335958589c172df88e059bf0738cac/addons/stock_account/models/stock_move.py#L314 opw-6323645 Forward-Port-Of: odoo/odoo#284251 Forward-Port-Of: odoo/odoo#273102
This fixes an issue where retrying a rejected simplified Saudi e-invoice could fail because the QR code was missing. The system now recreates the QR code from the invoice submission data during retry, helping businesses resubmit rejected invoices without errors while keeping normal QR display rules unchanged.
Original PR description
- When a simplified (B2C) invoice is rejected by ZATCA and subsequently retried, its state remains rejected. The QR code computation therefore returns an empty value for the rejected invoice, as the computation is primarily intended for the post-EDI state. During the retry, this results in a traceback when the QR code is applied to the XML. - Regenerate the QR code directly from the submission data when preparing a new B2C XML, instead of relying on the state-dependent QR code field. This preserves the existing QR visibility rules for the final invoice. task-6485555 Forward-Port-Of: odoo/odoo#284733 Forward-Port-Of: odoo/odoo#283534
Resumed shopping carts now recalculate the selected delivery cost after product prices are refreshed at checkout. This prevents customers from incorrectly keeping free shipping when an updated order total no longer qualifies, while preserving selected pickup locations for click-and-collect orders.
Original PR description
Steps to reproduce ================== 1. Configure a delivery method with free shipping above a threshold 2. Add a product to the cart above that threshold, select the delivery method and leave the…
Steps to reproduce ================== 1. Configure a delivery method with free shipping above a threshold 2. Add a product to the cart above that threshold, select the delivery method and leave the cart unfinished 3. Lower the product price below the threshold 4. Recover the cart and confirm the order from /shop/checkout => The product prices are refreshed, but shipping stays free although the new total is below the threshold. Root cause ========== Since [1], nothing re-rates the carrier after /shop/confirm_order refreshes the cart prices: the delivery method is selected before the confirmation. In 17.0, the payment page auto-clicked the selected carrier on load, which re-rated the shipping cost and masked the issue. Fix === Re-rate the selected delivery method in `shop_confirm_order` after the prices have been recomputed, as `_cart_update` already does. [1]: https://github.com/odoo/odoo/commit/8e2b6cede55b51f7ccdbe7601aa7e6035fd6f9fe opw-6383849 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284606 Forward-Port-Of: odoo/odoo#276905
Fixed an issue that could prevent the Assets list from opening when older or inconsistent analytic distribution data referenced deleted accounts. Users can now access the list view without getting stuck in an error loop, while the invalid underlying data remains unchanged for later correction.
Original PR description
Issue - If there are any account.asset records with analytic distributions with accounts that do not exist, it causes a recursive traceback when opening the list view of the `account.asset` model. The issue stems from `jsonToData` attempting to save the distributions json via the `save` call, where one (or multiple) accounts are non existent, which in turn runs `jsonToData` after refetching via the `load` call - overwriting `record.data` with the original, still-corrupt JSON. This creates a loop with no exit condition. Solution - In the Assets list every row is readonly, so `save()` is never reached, so `root.load()` never fires, so there is no reload to re-read the corrupt JSON. Makes the list accessible, even though the JSON values for the `analytic_distribution` are invalid. opw-6500446 Forward-Port-Of: odoo/odoo#285527 Forward-Port-Of: odoo/odoo#285381
This fix prevents custom website buttons from losing their gradient background when a user changes the button text color. It helps website editors keep the intended button design without needing to reapply styling.
Original PR description
Steps to Reproduce : 1. Go to Website → Edit Mode 2. Add a snippet with button 3. Click on button and change its type to : " Custom" 4. Apply the gradient type color in fill color option 5. Apply any…
Steps to Reproduce : 1. Go to Website → Edit Mode 2. Add a snippet with button 3. Click on button and change its type to : " Custom" 4. Apply the gradient type color in fill color option 5. Apply any color in text color option 6. You will notice that the gradient type color in fill color option is removed. Problem: Since [this commit][1] new button style options have been added to the sidebar. If one changes the style of a button to custom, changes the background to gradient, and tries to change the text color, the background gradient is removed. Cause: Whenever a gradient is added either to text or as a background, it is applied as a background image. In the case of a text gradient, an additional class, `text-gradient`, is applied for correct styling. Once a change to either color or background/fill is applied that is not a gradient color change, the background image of the element would be reset to nothing. This is the result of [this line][2] from a [previous commit][3]. In the case of a button, this meant changing the font color would reset the background. That is not the desired outcome. The flaw was only discovered once new options were added to change non-text/font elements' backgrounds to gradient. Solution: An additional check has been added to see if the element being edited is text. If so, and it's a gradient style being changed, we remove the background image. Otherwise it is kept so that the button case from above is resolved. [1]: https://github.com/odoo/odoo/commit/2bf1db001b195480b963b338583c170aa1c009a3 [2]: https://github.com/odoo/odoo/blob/8e0845712f462ecfafd2176406dcbafc869a5564/addons/html_editor/static/src/main/font/color_plugin.js#L575 [3]: https://github.com/odoo/odoo/commit/8e0845712f462ecfafd2176406dcbafc869a5564 task-6247134 Forward-Port-Of: odoo/odoo#285063 Forward-Port-Of: odoo/odoo#279070
This update prevents invoice printing from failing when an Argentine company's partner record contains a VAT number that is valid in another country but not a valid Argentine CUIT. It improves reliability for Argentine localization users by allowing invoices to print instead of showing an error.
Original PR description
When printing an invoice, a traceback will occur if the company's partner has an invalid CUIT. Steps to reproduce the error: - Install ``l10n_ar_edi`` module with demo data - Switch to ``(AR)…
When printing an invoice, a traceback will occur if the company's partner has an invalid CUIT. Steps to reproduce the error: - Install ``l10n_ar_edi`` module with demo data - Switch to ``(AR) Exento`` Company - Go to Invoicing > Configuration > Journals > Open ``Ventas Preimpreso`` journal > ARCA POS System: ``Electronic Invoice - Web Service`` > Save - Create a new invoice with ``ADHOC SA`` partner > Confirm the invoice - Open the ``(AR) Exento`` partner and set the VAT to ``BE0477472701`` - Open the Invoice > print Traceback: ```py ValueError: invalid literal for int() with base 10: 'BE0477472701' ``` After this [commit], companies outside the EU can use European VAT numbers. Consequently, an Argentine partner can have a CUIT number such as ``BE0477472701``, which is valid as a Belgian VAT number but not as a CUIT. When printing the invoice, the ``l10n_ar_vat`` field is computed from the partner's VAT and its value is passed to ``int()``, causing a traceback at the following line: https://github.com/odoo/enterprise/blob/d55486866d09f8aa87c2003dab722cfa323068b4/l10n_ar_edi/models/account_move.py#L138 [commit]: https://github.com/odoo/odoo/commit/a2afe3292e1cd0a4f339dc47707e469653d13ea0 Enterprise PR: https://github.com/odoo/enterprise/pull/127820 sentry-7666042143 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284880 Forward-Port-Of: odoo/odoo#282454
Invoice printing in Argentina localization now avoids crashing when a company partner has an invalid CUIT tax ID. This helps users complete invoice printing more reliably and prevents an unexpected error message in a common accounting workflow.
Original PR description
When printing an invoice, a traceback will occur if the company's partner has an invalid CUIT. Steps to reproduce the error: - Install ``l10n_ar_edi`` module with demo data - Switch to ``(AR)…
When printing an invoice, a traceback will occur if the company's partner has an invalid CUIT. Steps to reproduce the error: - Install ``l10n_ar_edi`` module with demo data - Switch to ``(AR) Exento`` Company - Go to Invoicing > Configuration > Journals > Open ``Ventas Preimpreso`` journal > ARCA POS System: ``Electronic Invoice - Web Service`` > Save - Create a new invoice with ``ADHOC SA`` partner > Confirm the invoice - Open the ``(AR) Exento`` partner and set the VAT to ``BE0477472701`` - Open the Invoice > print Traceback: ```py ValueError: invalid literal for int() with base 10: 'BE0477472701' ``` The issue occurs because when the partner's identification type is CUIT, At [1] ``_run_check_identification()`` method does not include partners whose identification type has ``is_vat=True``. As a result, CUIT is not validated by ``_run_check_identification()`` method in ``l10n_ar`` module at [2]. So, partner's ``l10n_ar_vat`` field can be computed as ``BE0477472701``. Passing this value to ``int()`` raises the traceback during invoice printing at below line. https://github.com/odoo/enterprise/blob/d55486866d09f8aa87c2003dab722cfa323068b4/l10n_ar_edi/models/account_move.py#L138 [1]:https://github.com/odoo/odoo/blob/c2a39085ba0fbcf8a0e6a55228191e764499caea/addons/l10n_latam_base/models/res_partner.py#L24-L30 [2]:https://github.com/odoo/odoo/blob/c2a39085ba0fbcf8a0e6a55228191e764499caea/addons/l10n_ar/models/res_partner.py#L55-L65 Community PR: https://github.com/odoo/odoo/pull/282454 sentry-7666042143 Forward-Port-Of: odoo/enterprise#129449 Forward-Port-Of: odoo/enterprise#127820
Point of Sale preparation tickets now reprint correctly when an order includes combo products. This prevents silent printing failures in kitchen or preparation workflows, helping staff recover tickets reliably when needed.
Original PR description
Steps to reproduce: --- - Configure a Point of Sale with a preparation printer whose product categories contain the products of a combo. - Add the combo to an order and send it to preparation. - Try to reprint the order. Issue: --- - Nothing is printed for orders containing a combo, without any error being shown. Fix: --- - Store the combo children of a preparation change as plain ids and match the printer categories on those ids. task-6472281 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282663
Fixed an issue where commission plan calculations could fail when the same salesperson had multiple assignment rows in an overlapping plan. The system now checks each assignment separately, preventing crashes and ensuring overlapping plans are detected correctly.
Original PR description
Version: 19.4 Steps to reproduce: - Open the commission plans list with demo data - Open a plan whose salesperson has duplicate assignment rows in an overlapping plan Issue: When calculating other_plans, the code assumed each salesperson had only one assignment in an overlapping plan. It used filtered() and directly accessed date_from .If the salesperson was assigned multiple times in the same plan, filtered() returned multiple records, which caused the error and crashed the calculation. Fix: Loop over all matching rows one at a time. If any row's date range overlaps with the current assignment, flag the plan and stop. This avoids the multi record access while correctly detecting all overlap cases. Task ID: 6302927 Forward-Port-Of: odoo/enterprise#120576
Fixed an issue where regular timesheet users could lose access to Assistant Rules when Billing Rate Indicators were turned off. The Timesheets configuration menu now stays visible for users who need assistant-related settings, reducing confusion and avoiding the need for debug mode.
Original PR description
Steps to reproduce --- 1. Install sale_timesheet_enterprise. 2. Go to Timesheets > Configuration > Settings (as Admin). 3. Disable the "Billing Rate Indicators" setting and enable timesheet…
Steps to reproduce --- 1. Install sale_timesheet_enterprise. 2. Go to Timesheets > Configuration > Settings (as Admin). 3. Disable the "Billing Rate Indicators" setting and enable timesheet assistant. 4. Log in as a normal user with "Timesheets > Own timesheet" access. 5. Open the Timesheets app. Issue --- The "Configuration" menu is completely hidden. The regular user cannot access the "Assistant Rules" menu unless they turn on debug mode. Cause --- When the billing rates feature is turned off, the _load_menus_blacklist function hides the Enterprise Configuration menu. The logic used an and condition, meaning the menu was only kept visible if the user was an Assistant AND had Manager/Admin rights. This locked out standard users. Fix --- Change the blacklist condition. Allow the Enterprise Configuration menu to stay visible if the user needs it for the Assistant feature (when UoM is not Days), OR if the user is a Manager/Admin. References to check other issues https://github.com/odoo/enterprise/pull/120609 https://github.com/odoo/enterprise/pull/117984 task - 6470183 Forward-Port-Of: odoo/enterprise#128727 Forward-Port-Of: odoo/enterprise#128096
This fix prevents a shopper's personal contact name from being replaced by their company name when they enter a valid VAT number during checkout. It keeps customer and company records correctly separated, improving order accuracy and customer data quality.
Original PR description
Steps to produce: --- - Install website_sale module without demo. - Create a new product and publish it. - From the incognito, go to shop and add that product to cart. - While doing checkout > fill…
Steps to produce: --- - Install website_sale module without demo. - Create a new product and publish it. - From the incognito, go to shop and add that product to cart. - While doing checkout > fill the address form. - Add the all details including the company name and valid VAT. (ex. BE0477472701) - Submit the form. Issue: --- - When a public or guest user submits a new address with both a contact name and a company name along with a valid VAT number, the contact's name was being overwritten with the company name. Root cause: --- - The _compute_is_company heuristic in res.partner automatically sets is_company=True for partners with valid VAT. In [commit] `_create_or_update_address`, the condition `elif partner_sudo.is_company:` was designed to rename existing companies, but incorrectly caught newly created individuals marked as companies due to VAT, causing their name to be overwritten instead of creating a parent company. Solution: --- - Replaced the is_company check with explicit conditions: the partner has no parent_id, has contact-type child_ids. - This ensures the rename-company branch only fires for actual company heads that the logged-in user belongs to, not for individuals that happen to have is_company=True due to a valid VAT. [commit]: https://github.com/odoo/odoo/commit/8f3a32170c842f5f42edc79bf8620276f0da7be4 opw-6356772 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285495 Forward-Port-Of: odoo/odoo#275044
This fixes activity filters so "today" is based on the user's local calendar date instead of UTC. Users in time zones ahead of UTC will no longer see activities due today incorrectly listed as future activities for part of the day.
Original PR description
#### Description of the issue: Activity filters using context_today() bucket against the UTC date instead of the user's local date, off by one for part of the day. Partial revert of #265250 (e048bb5), scoped to PyDate: UTC getters are right for PyDateTime, wrong for a calendar day. #### Current behavior before PR: A Perth (UTC+8) user finds an activity due today under "Future Activities" from 00:00 to 08:00 local, while the chatter labels the same activity "Today". #### Desired behavior after PR is merged: context_today(), today and current_date return the user's local calendar day, so filters agree with the chatter. PyDateTime and PyTime keep the UTC getters; now and time.strftime() are unchanged. opw-6415985 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281453 Forward-Port-Of: odoo/odoo#278761
Original PR description
*: pos_self_order, website, portal, portal_rating, project, website_event, website_links, website_mass_mailing, website_slides, account_payment Several places create a Bootstrap 5 component…
*: pos_self_order, website, portal, portal_rating, project, website_event, website_links, website_mass_mailing, website_slides, account_payment Several places create a Bootstrap 5 component (Carousel, Modal, Dropdown, Tab, Popover, Tooltip, Collapse, Offcanvas) without ever calling .dispose() on teardown. Bootstrap keeps every instance in a page-global Map (not a WeakMap) keyed by its DOM element (see `elementMap` [1], so a missing dispose() permanently leaks the element. Three helpers centralize the fix and dedupe disposal per instance (safe even if several owners obtain the same instance, e.g. a popup surviving a builder re-render): getOrCreateBootstrapInstanceForInteraction and getOrCreateBootstrapInstanceForEditorPlugin get-or-create an instance and register its disposal on the owner's teardown, for Interaction and Plugin owners respectively; useBootstrapInstance is the Owl hook equivalent for Components. disposeBootstrapInstance disposes an instance right away (e.g. from a hidden.bs.modal handler) through the same dedup tracking, so it is never disposed twice. Mostly invisible in normal usage, but a severe leak in the JS unit test suite (thousands of mount/unmount cycles in one browser session): | Run | Scope | Memory before | Memory after | Percent | |-------------------------------|-------|--------------:|-------------:|--------:| | carousel_hook.js (16719 tests) | all | 934.5 MB | 363.2 MB | -61% | Runbot errors: - https://runbot.odoo.com/odoo/error/945770 - https://runbot.odoo.com/odoo/error/945772 [1]: https://github.com/odoo/odoo/blob/6d2fda1/addons/web/static/lib/bootstrap/js/dist/dom/data.js#L23