Monday, August 24, 2026
48 changes · saas-19.2
Enhancements to existing features
Stock quantity updates now reuse the same warehouse lookup when processing multiple products. This reduces unnecessary database work during batch operations, helping inventory updates run more efficiently without changing user workflows.
Original PR description
When `_inverse_qty_available` processes multiple products, it performs the same warehouse search for every eligible product, resulting in redundant queries during batch operations. Look up the warehouse lazily once and reuse it for all products in the recordset. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283564
General ledger reports can now include the invoice date when businesses add it as a report column. This helps finance teams review ledger entries with invoice timing information directly in the report, reducing the need for extra lookups.
Original PR description
If a column is added with `expression_label` equal to `invoice_date`, include that in results of `_report_custom_engine_general_ledger`. task-5917897 Forward-Port-Of: odoo/enterprise#128678 Forward-Port-Of: odoo/enterprise#113774
Resolved issues and error corrections
Credit card and cash journal statement lists can now open individual statements in the detail form. This fixes a dashboard workflow issue that prevented users from reviewing or editing statement details after selecting them.
Original PR description
Issue: When opening the credit card statements list view from clicking the "Statements" button in the accounting dashboard of a credit card journal, the resulting list view does not allow clicking on any of the items to enter the form view Steps to reproduce: 1. Create a credit card journal and some credit card statements 2. Go to the accounting dashboard, and click on the button with three dots to the upper right of the credit card journal card and click "Statements" 3. Try to click on any of the statements in the list view and it won’t open any of them Cause: The window action for credit card journals (action_credit_statement_tree) was missing the form view in the view_mode Solution: Add form to the view_mode of action_credit_statement_tree. The cash journal bank statements window action (action_view_bank_statement_tree) was also missing the form view, so it was added as well opw-6449315 Forward-Port-Of: odoo/odoo#282816
Code cleanup and technical improvements
This update removes unused invoice customization code that no longer affects behavior. It keeps the GCC invoicing module simpler and easier to maintain while relying on the standard Odoo invoice logic.
Original PR description
Remove create() and _compute_narration() method overrides from l10n_gcc_invoice as they only existed to call _load_narration_translation(), which has already been disabled. The parent class implementations handle all required functionality. Keeps the codebase clean by removing unnecessary method overrides. Forward-Port-Of: odoo/odoo#281565 Forward-Port-Of: odoo/odoo#281395
Documentation and clarification updates
A contributor has submitted their Individual Contributor License Agreement signature for Odoo. This is an administrative legal update that helps ensure future contributions can be accepted under the project's licensing terms.
Original PR description
This pull request submits my Odoo Individual Contributor License Agreement signature. Forward-Port-Of: odoo/odoo#282045
Miscellaneous changes
This fix prevents manufacturing orders from failing to save after quantity changes trigger background recalculations. It improves reliability for users editing production orders by ensuring temporary form data is handled safely before saving.
Original PR description
Version: --------- - saas-19.2+ Steps to reproduce: ------------------------ - Install `mrp` module - Create a BoM containing a component and a 60-minute operation duration - Create an MO for that…
Version:
---------
- saas-19.2+
Steps to reproduce:
------------------------
- Install `mrp` module
- Create a BoM containing a component and a 60-minute operation duration
- Create an MO for that BoM with a quantity of 1 and save it.
- Change the quantity to 2.
- Click somewhere in the form to trigger the onchange.
- Change the quantity to 5.
- Try to Save the MO.
Issue:
Saving the Manufacturing Order can raise:
AssertionError: Invalid falsy real id
Cause:
-------
Clicking somewhere after setting the quantity to 2 triggers an onchange; it does not save the MO yet.
During this onchange, Odoo works with virtual copies of the MO and its one2many move records. Recomputing the quantity can replace or remove one of these virtual component or finished moves.
When the onchange response is generated, `RecordSnapshot.diff()` compares the one2many value before and after the onchange:
https://github.com/odoo/odoo/blob/15dc1c48f2eeffaf444c88e94d16a952faa830e8/addons/web/models/models.py#L2280-L2283
For a removed one2many line, it generates the following command:
Command.delete(id_.origin or id_.ref or 0)
A persisted move has an `origin`, so the command contains its database ID. However, a virtual move created during the onchange has neither an `origin` nor a `ref`. Its identifier therefore falls back to `0`.
For example, the onchange response can contain:
'move_raw_ids': [
(2, 0, 0),
(1, 123, {'product_uom_qty': 2}),
]
In these commands:
- `(2, 0, 0)` means DELETE the virtual move whose ID became `0`.
- `(1, 123, {...})` means UPDATE the persisted move with ID `123`.
The web relational model applies and accumulates these commands in the form state while processing successive onchanges:
https://github.com/odoo/odoo/blob/15dc1c48f2eeffaf444c88e94d16a952faa830e8/addons/web/static/src/model/relational_model/static_list.js#L574-L691
After changing the quantity again to 5, the valid update is refreshed, but the deletion command for the discarded virtual record can remain. The final save payload can consequently be:
{
'product_qty': 5,
'move_raw_ids': [
(2, 0, 0),
(1, 123, {'product_uom_qty': 5}),
],
}
Saving the form calls `web_save()`, which forwards this payload to `mrp.production.write()`:
https://github.com/odoo/odoo/blob/15dc1c48f2eeffaf444c88e94d16a952faa830e8/addons/web/models/models.py#L79-L86
The resulting call flow is:
mrp.production.web_save()
-> mrp.production.write()
-> BaseModel.write()
-> One2many.write_real()
-> flush()
-> stock.move.browse([0])
-> AssertionError: Invalid falsy real id
For a DELETE command, the one2many writer adds the command ID to `to_delete`. During `flush()`, it browses all collected IDs before unlinking them:
https://github.com/odoo/odoo/blob/15dc1c48f2eeffaf444c88e94d16a952faa830e8/odoo/orm/fields_relational.py#L1031-L1058
PR https://github.com/odoo/odoo/pull/227477 made browsing collections containing falsy real IDs invalid. This is intentional because `0` or `False` cannot identify a persisted database record.
FIX:
----
BackPort PR: https://github.com/odoo/odoo/pull/274755
it Fix payload.
After fix Payload:
<img width="612" height="517" alt="image" src="https://github.com/user-attachments/assets/856543b1-a466-44ff-bef8-df476234ac78" />
Before Fix Payload:
<img width="791" height="684" alt="image" src="https://github.com/user-attachments/assets/5be4a766-0c9d-4c80-8e16-2b6035f086cc" />
------
opw-6471907
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix updates online store tests so inactive products are correctly excluded during test runs. It prevents false test failures and supports more reliable quality checks, with no customer-facing change.
Original PR description
Description of the issue/feature this PR addresses: Addresses an issue causing test failures by ensuring that [inactive products](https://github.com/odoo-dev/odoo/blob/dbc917ddc263a330ff70f5edec716ccafe88d7a6/addons/website_sale/tests/test_product_filters.py#L93-L99) are filtered out rather than leaking from the environment into the test execution. I have verified that this issue does not allow [inactive records to leak to customers](https://www.odoo.com/mail/message/1151343506). runbot-242426
Corrects the Mexican chart of accounts so accumulated depreciation and amortization accounts are treated as asset-related accounts. This ensures asset depreciation entries calculate and record proper values instead of showing zero, improving financial accuracy for Mexican companies.
Original PR description
Issue: When creating an asset using an "154.01.01 Vehicles", the depreciation values of the journal entries created are zero Steps to reproduce: 1. Install l10n_mx and enter a Mexican company 2.…
Issue: When creating an asset using an "154.01.01 Vehicles", the depreciation values of the journal entries created are zero Steps to reproduce: 1. Install l10n_mx and enter a Mexican company 2. Create an asset and setting the fixed asset account as 154.01.01 Vehicles 3. Click on "Compute Depreciation" and in the "Depreciation Board" page, all the journal entries created will not have any depreciation values Cause: In the l10n_mx chart of accounts, all accumulated depreciation accounts are set as "expense_depreciation" whereas they should be asset accounts because accumulated depreciation accounts are used to credit asset accounts to decrease asset values. If an account of type "expense_depreciation" is used, then when the depreciation account is credited and the expense account is debited, all financial events will occur within expense accounts, which is why no depreciation values were recorded as the asset balances stay the same. Additionally, the "asset_depreciation_account_id" field on "account.account" has a domain restricting selection to "account_type" of "asset_fixed" or "asset_non_current" Solution: Change the "account_type" of l10n_mx accumulated depreciation accounts from "expense_depreciation" to "asset_fixed" and l10n_mx accumulated amortization accounts from "expense_depreciation" to "asset_non_current" Updrade PR: [odoo/upgrade/pull#10936](https://github.com/odoo/upgrade/pull/10936) opw-6359618 Forward-Port-Of: odoo/odoo#278185
This fixes an issue where product costs could be overstated after a sale was delivered, returned, credited, and sold again. Credit notes are now included when calculating previously posted cost of goods sold, so financial reporting reflects the correct cost amount.
Original PR description
**Steps to reproduce:** - create a storable product with a positive quantity a cost of 10 and average perpetual category - confirm a SO for 1 quantity, validate delivery - confirm invoice for 1 (COGS…
**Steps to reproduce:** - create a storable product with a positive quantity a cost of 10 and average perpetual category - confirm a SO for 1 quantity, validate delivery - confirm invoice for 1 (COGS should be 10) - return the delivery and validate - create a credit note from the invoice for 1 and confirm (COGS should be 10) - return the return and validate - change the standard price to 100 - create an invoice from the SO for 1 and confirm **Current behavior:** cogs are 190 **Expected behavior:** cogs should be 100 **Cause of the issue:** _get_posted_cogs_value doesn't take into account the credit notes (only the account moves with type 'out_invoice' are taken into account in the sum) https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/sale_stock/models/account_move.py#L185-L186 So in our case the first invoice and the credit note don't cancel out each other. The same goes for _get_cogs_qty (which returns the total cogs past + current), in the past cogs it doesn't take into account the quantities of the credit note. https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/sale_stock/models/account_move.py#L172-L174 So the quantity of the first invoice and the one of the credit note don't cancel out each other. As a result, the return value from _get_cogs_value() for the second invoice is : price unit = 100 returned by _get_cogs_price_unit() https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/account_move_line.py#L68 which returned the standard price because the product has an average cost method https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/stock_move.py#L275-L280 cogs_qty = 2 (instead of 1 if credit was taken into account as -1 in the sum) self._get_posted_cogs_value() = 10 (instead of 0 if credit note cogs were taken into account in the sum as -10) return value = (100 * 2 -10)/1 = 190 https://github.com/odoo/odoo/blob/0824dc24665de6bfa805d540e756cdcb006edba6/addons/stock_account/models/account_move_line.py#L75 **fix:** if we take into account the credit note the return value will be : (100 * 1 - 0)/1 = 100 the mechanism of the already posted cogs value is there for cases where we only delivered a part of the quantity and then delivered the rest, but in the case where we delivered and then returned (with credit notes) it shouldn't have an impact. Thus the idea to include the credit note so that it can cancel out the first invoice opw-6426111 Forward-Port-Of: odoo/odoo#282893
This fixes a scheduled email processing check so the email queue job can properly record its progress when it runs. It also adds clearer logging of the sending limit, helping support teams investigate silent email queue failures caused by memory limits.
Original PR description
The changes introduced by https://github.com/odoo/odoo/commit/19d5367862528979abdcd411095f18d36bdbe7b8 aimed at aligning the mailing cron job logic with the new `_commit_progress` system. While doing…
The changes introduced by https://github.com/odoo/odoo/commit/19d5367862528979abdcd411095f18d36bdbe7b8 aimed at aligning the mailing cron job logic with the new `_commit_progress` system.
While doing so, it accidentally added an if condition based on `self.env.get('ir_cron')`, which will always return False and never run the progress commit as intended.
To address this, in this PR:
- we change the condition to `if self.env.context.get('cron_id'):`, the cron_id context variable being set when the method was called from a scheduled action
- additionally we take the occassion to add an info log that outputs the computed send limit at the time the method was triggered. This will make it easier to investigate the logs ad-hoc in situations where the "Mail: Email Queue Manager" cron job fails silently because of a memory limit error. A high send limit (batch_size) increases the chances of memory errors proportionally. Knowing what the exact sending limit was at a given point in time makes investigation easier when trying to build a sequence of past events that could explain issues related to email sending.
OPW-6396087
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283402
Forward-Port-Of: odoo/odoo#282892This fixes seven mislabeled entries in the Mexican chart of accounts so exported electronic accounting files use the official SAT descriptions. The change helps Mexican companies avoid mismatches between Odoo's account group names and government catalogue terminology, while leaving trial balance and journal policy exports unchanged.
Original PR description
Seven entries of the Mexican chart of accounts template carry a name belonging to a **different** group, copied from a neighbouring entry. Each record's XML ID still states the intended name, which…
Seven entries of the Mexican chart of accounts template carry a name belonging
to a **different** group, copied from a neighbouring entry. Each record's XML ID
still states the intended name, which is what this restores.
| Code | Field | Before | After |
|---|---|---|---|
| `6` | `name@es` | Gastos generales | Gastos |
| `252.07` | `name@es` | `account_subgroup_hipotecas_por_pagar_a_largo_plazo_nacional` | Hipotecas por pagar a largo plazo nacional |
| `602` | `name`, `name@es` | Cost of sales / Costo de venta | Selling expenses / Gastos de venta |
| `613` | `name@es` | Amortización contable | Depreciación contable |
| `614` | `name` | Accounting depreciation | Accounting amortisation |
| `701.06` | `name`, `name@es` | Interest on foreign bank charges / Intereses a cargo bancario extranjero | Interest payable by national natural persons / Intereses a cargo de personas físicas nacional |
| `702` | `name@es` | Utilidad cambiaria | Productos financieros |
### Why it is not cosmetic
The electronic accounting Chart of Accounts XML takes the `Desc` attribute of
every `<Ctas>` element from the *account group name* — `cfdicoa.xml`
(`t-att-Desc="account.get('name')"`), fed by `trial_balance.py`
`_l10n_mx_get_coa_values()`. Any `es_*` database therefore declares:
```xml
<catalogocuentas:Ctas CodAgrup="702" NumCta="702" Desc="Utilidad cambiaria" Nivel="1" Natur="A"/>
```
whereas the SAT catalogue (Anexo 24) publishes `702` as *Productos financieros*,
with `702.01 Utilidad cambiaria` … `702.10 Otros productos financieros` beneath
it. `CodAgrup` comes from `code_prefix_start` and stays correct, so the file
still validates against the XSD, but the declared description does not match the
official nomenclature. Trial Balance and Pólizas are unaffected — neither
exports group names.
### Evidence
- `252.07` contains its own XML ID as the Spanish name.
- `602` duplicates `501.01`, yet its children are `Sueldos y Salarios`,
`Compensaciones`, `Tiempos extras`.
- `613` and `614` are swapped in one language each: `613`'s children are
depreciations, `614`'s are amortisations.
- `701.06` duplicates `701.05` in both languages; the correct name is symmetric
to `701.07` and to `702.06`.
- `6` is the only single-digit root group whose Spanish name does not match its
XML ID (`account_group_gastos`).
### Notes
Introduced in d782b8b92557; correct in 15.0, where the names lived in
`account.account.tag.csv`. Still present in 18.0, 19.0 and master, hence
targeting 17.0. Template data only — existing databases are unaffected until the
chart is (re)installed, and renaming a group moves no balance.
Forward-Port-Of: odoo/odoo#277426
Forward-Port-Of: odoo/odoo#277891The HTML editor now preserves background colors when users turn colored text into lists or turn list items back into normal paragraphs. This prevents formatting from unexpectedly disappearing, helping users keep document and website content visually consistent.
Original PR description
Problem: Background color was lost both when converting text with a background color into a list item and when converting a list item with a background color back into a paragraph. Cause: - `insertListAfter` only copied `color` from the font wrapper to `li.style.color`, ignoring `background-color`. - Unwrapping a list item (`ListPlugin`) extracted `color`, `font-size`, and `text-align`, but ignored `backgroundColor`. Solution: - Preserve `background-color` from font wrapper onto `li.style.backgroundColor` when creating a list. - Restore `li.style.backgroundColor` onto a `<font>` wrapper when unwrapping a list item. Steps to reproduce: - Apply background color to a paragraph and toggle list -> background color is lost. - Apply background color to a list item and toggle list off -> background color is lost. opw-6481665 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283158
This fix restores breadcrumb navigation on customer portal list pages where users previously saw only the page title. It improves navigation clarity across several portal-facing business areas, including sales, purchases, projects, timesheets, accounting, loyalty, subcontracting, and partner assignment.
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. 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
The HTML editor now positions the drag-and-drop move handle on the correct side when editing right-to-left content. This improves usability for users working in RTL languages by making block movement controls appear where expected.
Original PR description
Problem: In MoveNodePlugin, `setMovableElement` sets the position of the drag-and-drop handler without considering `this.config.direction === "rtl"`. The handler is placed on the left side regardless of text direction. Solution: - In RTL mode, calculate the handle position from the right edge of the element so it is placed on the right side with the same distance as in LTR. - Update hover hooks, editable bounds, and dropzone rectangles for RTL mode. Steps to reproduce: 1. Open the editor in RTL mode. 2. Hover over a movable block element (e.g. `<p>`). => The move handle appears on the left side of the element instead of the right. task-6442717 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283662 Forward-Port-Of: odoo/odoo#281249
Shipping charges are now recalculated when a customer confirms a recovered cart after product prices have changed. This prevents orders from incorrectly keeping free shipping when the updated cart total no longer qualifies, improving pricing accuracy at checkout.
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#282963 Forward-Port-Of: odoo/odoo#276905
New onsite learning events created from the Onsite view or an employee resume now remain visible immediately after they are saved. This avoids confusion for HR users by automatically registering the current employee and relaxing overly strict visibility rules.
Original PR description
Onsite events created from the "Onsite" view or the employee resume selector do not appear immediatlely after creation This occurs because currently the domain for onsite events requires that the…
Onsite events created from the "Onsite" view or the employee resume selector do not appear immediatlely after creation This occurs because currently the domain for onsite events requires that the event to have multiple slots as well as to have at least one employee registered to it. Therefore, newly created records often fail these criteria and remain hidden. In further versions, this pr: https://github.com/odoo/odoo/pull/246285/ changes the domain of the event selector in the employee resume by removing the dependency on the multiple slots and filtering by the specific employee for registration. This change is not stable to backport as it indroduces the `employee_id` field as an invisible field in the xml to be able to compare in the domain. This commit partly changes both domains to not require the multiple slots anymore, while still showing all events for which an employee is registered. This commit also ensures that when an event is created from the Onsite view or selector, the current user's employee will be registered to it. Steps to reproduce - Go to employees->Learning->Onsite - Select New and create an event - Go back to Onsite Courses - You will not see the created event (unless it is multi_slot and an employee was registered) opw-5915686 Forward-Port-Of: odoo/odoo#258952
Inventory users can now validate dropship transfers for average-cost products when landed costs are enabled. This prevents an access error in a normal sales and purchasing flow, reducing operational delays without changing the business process.
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#273102
Cancelling the product configurator in Point of Sale no longer leaves optional products visible. This prevents staff from accidentally adding extras for a product that was not actually added to the order.
Original PR description
When discarding the product configurator, we still showed the optional product. We no longer do that as no one wants to add optional products to a not-added product. task-6442422 Forward-Port-Of: odoo/odoo#283378 Forward-Port-Of: odoo/odoo#282916
This update cleans and validates message posting data before it is accepted, using the current user's permissions as the guide. It helps prevent inappropriate or unexpected data from being included in messages, improving reliability and control in the messaging flow.
Original PR description
This change sanitizes some post data before allowing the post, making sure the data received by `message_post` is clean based on the current user. part of task-6452761 Forward-Port-Of: odoo/odoo#282812 Forward-Port-Of: odoo/odoo#280894
The translation button now saves edits made inside related-record pop-up dialogs before opening translations. This ensures users translate the current text they just entered, rather than outdated or empty saved content, while preserving existing behavior for editable lists.
Original PR description
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened…
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened in an x2many form dialog keeps its changes for itself until the dialog is saved, see https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/web/static/src/model/relational_model/static_list.js#L193. Its pending changes are not part of the root record changes, so saving the root sends nothing to the server, and the translation dialog then shows the stored terms instead of the current content, or no terms at all when the stored value is empty. The fix changes openTranslationDialog in translation_button.js, the place that decides which record to save. When the record keeps its changes for itself (record._noUpdateParent), the record is saved directly, like the button did before the commit above. The root record is still saved in the other cases, so the editable list case that commit fixed keeps working. Steps to reproduce: 1. Activate a second language in Settings > Translations > Languages 2. Open the Surveys app, open a survey and click a question in the Questions tab 3. In the Description tab, change the description 4. Click the EN button on the description field => the translation dialog shows the terms of the previous description, not the current one Ticket [link](https://www.odoo.com/odoo/project.task/6237291) opw-6237291 Forward-Port-Of: odoo/odoo#269507
The mail compose process now uses the current progress-tracking method instead of an outdated one. This prevents unnecessary warning tracebacks in server logs during automated mail processing, making monitoring cleaner without changing user-facing behavior.
Original PR description
Since 19.0 `_notify_progress`` is deprecated in favor of `_commit_progress``. See: https://github.com/odoo/odoo/commit/ee337934f9885834d95592946f435c6e1c8ef970 Currently, the mail compose wizard still calls an explicit _notify_progress followed by an explicit commit. This leads to warning tracebacks being dumped into the server logs (for example everytime the "Mail Marketing: Process queue" cron runs). We replace it with an equivalent `_commit_progress` call, which should log the progress and implicitly take care of the cursor commit. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282926
Chat windows on mobile screens can now have their display order adjusted by other parts of Odoo instead of always using one fixed position. This helps prevent chat windows from accidentally covering or being covered by other interface elements in customized setups.
Original PR description
The z-index of chat windows on mobile views was previously fixed at `1020`, preventing other modules from adjusting their stacking order. This commit introduces a configurable z-index for chat windows, defaulting to `1020` while allowing other modules to override it when needed. task-6412411 Forward-Port-Of: odoo/odoo#283671 Forward-Port-Of: odoo/odoo#283178
This fixes an issue in the HTML editor where selected linked text using a gradient style could disappear. Users can now see and edit gradient-styled links more reliably, reducing confusion while editing website or content text.
Original PR description
Problem: When text formatted with `.text-gradient` is inside a link with `.o_link_in_selection`, the selected text becomes invisible. `.text-gradient` sets `-webkit-text-fill-color: transparent`, which prevents `color: black !important` on `.o_link_in_selection` from taking effect. Cause: `-webkit-text-fill-color: transparent` from `.text-gradient` overrides standard text `color` rendering, causing the text to stay transparent against the selection highlight background. Solution: Set `-webkit-text-fill-color: black` on `.o_link_in_selection` to ensure text inside gradient links is rendered in black and remains clearly visible when selected. Steps to reproduce: - Add text "ABCD". - Apply gradient color to all text. - Create a link on "BC". - Place cursor/selection inside the new link. - Observe that the text is not visible. opw-6479350 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282952
This fixes an issue where pressing Shift+Enter in Safari created a full paragraph break instead of a simple line break in the editor. Users editing Knowledge articles on Safari can now format text consistently with other browsers.
Original PR description
**Steps to reproduce:** - Use a Mac with Safari - Install Knowledge app - Go to any article - Press Shift+Enter to try to enter a soft line break - Hard split is done instead **Issue:** Shift+Enter causes a `insertParagraph` event instead of `insertLineBreak` in Safari, which triggers the `SplitPlugin` instead of the `LineBreakPlugin`. **Fix:** Check if the browser is Safari and call `insertLineBreak` from the `SplitPlugin` (when needed) by listening to the "keydown" events. (note: I was not able to find any other key combination to properly trigger the `insertLineBreak` event in Safari) opw-6413507 Forward-Port-Of: odoo/odoo#281458
Website editors can now directly edit previously locked areas in mega menu templates, such as footers and logo sections. This removes a small but frustrating limitation in the website builder and makes menu customization smoother.
Original PR description
### Issue: Some elements in mega menu templates are not editable inline in the website builder. ### Steps to reproduce: - Go to Website > Site > Menu Editor and add a mega menu item. - Edit the mega menu and set its template (e.g. 'Thumbnails' or 'Logos'). - Try to inline edit certain sections (e.g. footer or logos container). ### Reason: `BuilderContentEditablePlugin` does not apply `contenteditable="true"` to these elements because they do not match any of the selectors defined in `content_editable_selectors`. ### Fix: Add missing element classes to `content_editable_selectors` so that these elements become editable inline. task-[6116253](https://www.odoo.com/odoo/project/974/tasks/6116253) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263021
Restaurant staff can now split bills for combo meals with repeated choices more accurately. When the same combo option is selected multiple times, the split screen now selects the full quantity instead of only one item, helping avoid billing mistakes.
Original PR description
Steps to reproduce: --- - Install `pos_restaurant` demo data. - Open a session for `Restaurant`. - Go to any table. - Add a Sushi Lunch Combo line with the same sushi choice multiple times. - Click the "More" button and select "Split". - Click on any combo product line. Issue: --- - Only one quantity is selected instead of the full combo choice quantity. Cause: --- - Combo child lines were incremented by a fixed value of `1` during split, without considering the quantity ratio between the combo root line and combo child lines. Fix: --- - Compute the selection step based on the combo line quantity relative to the combo root line quantity. - Properly update split quantities for repeated combo choices. - Added test coverage for combo lines with repeated quantities. task-6197879 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282717 Forward-Port-Of: odoo/odoo#264049
The web search now safely ignores a saved default filter when it points to a missing related record. This prevents users from seeing a crash when opening affected views and keeps the search experience uninterrupted.
Original PR description
…'t exist Have a search view with a m2o field Have an action that sets search_default_m2o: [/BAD ID/] Before this commit there was a crash After this commit, we simply ignore the filter. task-6469841 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#282738
Dragging an unscheduled planning slot onto the calendar now works reliably when Studio scheduling is enabled. The fix restores required scheduling details and prevents a missing-date error, avoiding disruptions for users planning work.
Original PR description
Steps to reproduce: ------------------------- 1. Install `sale_planning` and `web_studio` with demo data. 2. Open the Planning calendar view. 3. Enable the "Scheduling" option from Studio and close…
Steps to reproduce:
-------------------------
1. Install `sale_planning` and `web_studio` with demo data.
2. Open the Planning calendar view.
3. Enable the "Scheduling" option from Studio and close it.
4. Drag an unscheduled slot onto the calendar.
Issues:
-----------
**Issue 1:**
```python
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 142, in write
self.assign_slot(vals)
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 159, in assign_slot
new_vals, tmp_sale_order_slots_to_plan, resource = slot._get_sale_order_slots_to_plan(vals, slot_vals_list_per_employee)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 228, in _get_sale_order_slots_to_plan
)._get_resource_work_info(vals, slot_vals_list_per_resource)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 366, in _get_resource_work_info
assert self.env.context.get('default_end_datetime')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
```
**Issue 2:**
```python
UncaughtPromiseError > TypeError
Uncaught Promise > Cannot read properties of undefined (reading 'endOf')
TypeError: Cannot read properties of undefined (reading 'endOf')
```
Cause:
----------
Since commit 1ce0dc8, the scheduling/unscheduling logic has been moved to the generic calendar implementation. However, the generic scheduling flow does not provide the `default_end_datetime` context required by sale_planning. As a result, sale_planning raises an `AssertionError` while scheduling a slot.
Additionally, when no date is available, attempting to call `endOf()` raises a `TypeError`.
Solution:
------------
Introduce a generic scheduling context hook in the calendar model and override it in Planning to provide the `default_end_datetime context when scheduling a slot.
This restores the context expected by` sale_planning`, prevents the `AssertionError`, and avoids calling `endOf()` on an undefined date to resolve `TypeError`.
**NOTE:**
This issue has already been resolved in the later versions (saas-19.4) as part of the scheduling/unscheduling refactoring. This commit backports the minimal changes required to fix the issue in this version.
References: f0f7b34 & https://github.com/odoo-dev/enterprise/commit/f82d073d17ce61a2ff39496364d3dced814ee90a
Related enterprise pr: https://github.com/odoo/enterprise/pull/127196
opw-6442889
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281178Sales users limited to their own documents can now cancel sales orders that include loyalty rewards without hitting an access error. The fix ensures temporary loyalty point records are cleaned up correctly during cancellation, reducing disruption in the sales workflow.
Original PR description
Steps to produce: --- - Install `sale_management` and `sale_loyalty` module without demo. - From sales > products > discounts & loyalty, create new loyalty card program and save. - Now create new…
Steps to produce: --- - Install `sale_management` and `sale_loyalty` module without demo. - From sales > products > discounts & loyalty, create new loyalty card program and save. - Now create new product of 100$. - Create a user which have sales rights as `user: own documents only`. - With that user, create new sale order with product and confirm. - Try to cancel the order. Issue: --- - It shows the access error: ```py You are not allowed to delete 'Sale Order Coupon Points - Keeps track of how a sale order impacts a coupon' (sale.order.coupon.points) records. This operation is allowed for the following groups: - Sales/Administrator Contact your administrator to request access if necessary. ``` Root cause: --- - Users with the `Sales: Own Documents Only` access right only have read permissions ([1]). When they cancel a Sales Order, the `_action_cancel` method attempts to clean up the temporary pending points allocated to the order by calling `self.coupon_point_ids.unlink()`. Because this call is executed without elevated privileges, the system blocks the deletion and raises an Access Error Solution: --- - Added `.sudo()` to the `unlink()` call for `coupon_point_ids` in the `_action_cancel` method. This ensures the pending point records are cleaned up with the necessary elevated privileges. [1]https://github.com/odoo/odoo/blob/23af2b443735c6d3a2f64e44f9ea5da45638b052/addons/sale_loyalty/security/ir.model.access.csv#L16 opw-6453016 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283535 Forward-Port-Of: odoo/odoo#281477
Custom-hour time off requests that start and end at 12:00 AM are now treated as zero hours instead of being expanded to the employee’s full working day. This prevents incorrect leave balances and records when employees or HR teams enter midnight as an explicit time boundary.
Original PR description
Issue: A custom-hours time off from 12:00 AM to 12:00 AM was computed as the full working schedule instead of 0:00. Steps to reproduce: - Create a time off type using custom hours - Create a time off on one day - Set the time from 12:00 AM to 12:00 AM Cause: https://github.com/odoo/odoo/blob/39916affb0694d0d68c3edabd3472c3dccfb3704/addons/hr_holidays/models/hr_leave.py#L472-L478 treated 0.0 as a missing hourly bound and replaced it with calendar hours through `_get_hour_from_to()` Solution: Keep explicit request_hour_from/request_hour_to values for hourly time off so midnight remains a valid bound. opw-6253807 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures Brazilian point-of-sale tax adjustment entries select the correct sales tax instead of sometimes using a matching purchase tax. It prevents accounting entries from becoming unbalanced, improving reliability of POS fiscal records.
Original PR description
The chart template gives the same Avatax code and price_include_override to the sale and the purchase tax, and creates both in the same transaction. Without an explicit type_tax_use the lookup used to return either of them at random, and picking the purchase one left the entry unbalanced. The purchase taxes got their Avatax code in 18.4+. https://github.com/odoo/enterprise/pull/101072 runbot-945969 Forward-Port-Of: odoo/enterprise#128818 Forward-Port-Of: odoo/enterprise#128476
This fixes an issue that prevented users from entering and comparing budget amounts on the Moroccan Profit and Loss report. Businesses using Moroccan accounting reports can now rely on budget comparisons even when the report has multiple columns, including totals.
Original PR description
Before this commit, it was impossible to use budget on the Moroccan P&L, for the following reasons: - The feature was designed for one-column reports. MA's P&L uses 3, one of which is the total of…
Before this commit, it was impossible to use budget on the Moroccan P&L, for the following reasons:
- The feature was designed for one-column reports. MA's P&L uses 3, one of which is the total of the two others.
=> We remove that requirement, and make sure to always select the 'balance' column as the reference for the budget comparison.
- When trying to input a budget amount in the report, the amount disappeared entirely.
=> This was because the total column of report was not using 'balance' as its expression label. We fix that by rewriting the expression labels of that report.
The fact we hardcode the use of 'balance' is arguable. It is however not possible here to rely on some custom handler to change a specific option key that would be used to generate the budget comparison data, since some of those data need to be generated in the get_options, before _custom_options_initializer even gets called. This is the simplest approach, and this case is rare enough for us to deem it acceptable.
opw-6385229
Forward-Port-Of: odoo/enterprise#128861
Forward-Port-Of: odoo/enterprise#128266This fix ensures shifts without a linked sales order line still get a valid customer value instead of causing an error. It improves reliability when managing planned shifts in Sales Planning.
Original PR description
Before this commit, when the shift has no SOL set, the `_compute_partner_id` crashes because the value for partner_id field is not set for that shift. This commit fixes the compute method of partner_id to make sure the value is correctly set for all shifts.
This fix prevents the incoming invoice journal from being cleared for companies that cannot receive Peppol documents through the Documents app, such as French companies using electronic invoicing rules. Incoming Peppol documents will now continue to create vendor bills in the required journal instead of being incorrectly routed to Documents.
Original PR description
Peppol documents can be received in a journal or in the Documents app (peppol_reception_mode). Some companies cannot use Documents: _peppol_allows_document_reception() returns False and the journal…
Peppol documents can be received in a journal or in the Documents app (peppol_reception_mode). Some companies cannot use Documents: _peppol_allows_document_reception() returns False and the journal stays required. This is the case of French companies (via l10n_fr_pdp). The onchange of the settings and the import did not check this method. So on a French company with the mode set to 'documents': - the Settings cleared the journal on each opening, while it was still required - the incoming documents were saved in Documents instead of vendor bills Steps to reproduce: - Create a Belgian company, with a purchase journal, and register it on Peppol as receiver - Set the reception mode to "Receive in Documents" - Change the fiscal position to France, and install l10n_fr_pdp, the Peppol part is replaced by "French Electronic Invoicing", so the radio button is not visible anymore, but the company still has peppol_reception_mode == 'documents'. - Open the Settings again: the field "Incoming Invoices Journal" is empty. opw-6429691 Forward-Port-Of: odoo/enterprise#126462
This fix restores the breadcrumb navigation on portal list pages where it had been replaced by a repeated page title. Customers can more easily navigate back to the portal home area across appointments, helpdesk, subscriptions, documents, field service, and equity pages.
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
This fixes two mislabeled account group names used in Mexican trial balance reporting checks. It helps ensure the Chart of Accounts information prepared for SAT reporting matches the corrected official account group labels and keeps localization validation passing.
Original PR description
Enterprise companion of odoo/odoo#277615 — the forward-port to 19.0 of the `l10n_mx` fix that restores the SAT account group names copied from siblings. The `l10n_mx_reports` trial balance test asserts the full Chart of Accounts XML sent to the SAT with the group names hardcoded in the expected output. Two of them were wrong (copied from sibling groups) and are corrected by the community PR: - SAT group **602** (Gastos de venta): `Cost of sales` → `Selling expenses` (`Cost of sales` is 501.01). - SAT group **614** (Amortización contable): `Accounting depreciation` → `Accounting amortisation` (that name belongs to 613). Without this, `ci/l10n` fails on `TestL10nMXTrialBalanceReport.test_generate_coa_xml` and `...test_generate_coa_xml_with_prefix_7_accounts_having_debit_and_credit_tags`. Same branch name as the odoo PR so the mergebot pairs them. Forward-Port-Of: odoo/enterprise#125207
Belgian fixed monthly salaries are now prorated using the employee's expected hours for the full payslip period, rather than a single week's schedule. This prevents incorrect salary deductions and ensures employees are paid correctly when they work more or less than half of the period.
Original PR description
### Problem - Fixed salary payslips were not being prorated correctly. The 50% rule threshold was compared against `hours_per_week` (single week) instead of 50% of the theoretical hours for the…
### Problem
- Fixed salary payslips were not being prorated correctly. The 50% rule threshold was compared against
`hours_per_week` (single week) instead of 50% of the theoretical hours for the payslip period.
This led to incorrect salary deductions in all cases and the wrong computation path being taken when less than
50% of the month was worked.
### Solution
- Fix `_l10n_be_has_enough_paid_hours` to compare paid hours against
50% of theoretical hours instead of `hours_per_week` (which are calculated for the employee's `working schedule`)
### How it works
- For fixed salary (`wage_type = 'monthly'`), the quarterly hourly rule
is applied as follows:
- **Hourly rate** = `fixed_salary × 3 / 13 / theoretical_hours`
- **50% rule**:
- If more than 50% of theoretical hours were worked → deduct absences
from fixed wage
- If less than 50% of theoretical hours were worked → pay only the
hours worked
For variable salary (`wage_type = 'hourly'`), the employee is simply
paid for the number of hours worked during the period.
Task-6260378Splitting a multi-page PDF in Documents now keeps the resulting pages in a consistent order. This prevents users from seeing newly split files appear randomly, making document review and organization more predictable.
Original PR description
steps: - upload a multi-page pdf - split all the pages -> they now show in a random order The issue is that the current documents are sorted by create_date desc, but the split creates all the different documents at the same time so they are sorted in the order they happen to be on the disk. We now add a sort by id to act as a tie-breaker. opw-6176840 Forward-Port-Of: odoo/enterprise#128410 Forward-Port-Of: odoo/enterprise#117255
Android users can now download files opened from the mobile file viewer, such as images shared in Discuss. The change routes downloads through the mobile app's native download handling so Android accepts the file link instead of rejecting it.
Original PR description
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads…
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads using the HTTP protocol." downloadFile()'s GET-by-URL case fetches the URL via XHR, then saves the Blob response by clicking a hidden <a download> anchor on a blob: URL. Android's DownloadManager only accepts http(s) URLs, so it rejects that blob: URL instead of downloading anything. Patch downloadFile._download to hand the URL directly to a new mobile.methods.saveFile bridge method when available, the same way download._download already delegates to mobile.methods.downloadFile. Blob/string content downloads aren't handled here — the only such call site (spreadsheet JSON export) is debug-mode only, so this is left as a console.warn for now. Related to odoo/odoo@e83fd8c08c879f5e262d39f24edcb3f81238ea82 Code made by Claude Changes supervised by HUVW Forward-Port-Of: odoo/enterprise#128471 Forward-Port-Of: odoo/enterprise#127693
Cancelling a payslip now correctly resets related time off so it can be included when the payslip is recalculated. This prevents validated leave from being missed in payroll after a payslip is cancelled and returned to draft.
Original PR description
How to reproduce: - Create a payslip for an employee and validate it - Create a new time off for said employee during the same period as the payslip and validate it - Go back to the payslip, cancel it and reset it to draft - The new time off is not included in the payslip Reason: When a payslip is cancelled, if there are time off during the same period as the payslip, their state is not reset to "to compute in next payslip" and instead stays in "to defer to next payslip", causing the issue How it was fixed: Now, when a payslip is cancelled, the new function "return_time_off_to_normal" will catch all leaves that are in the same time frame as the payslip to reset their state to "to compute in next payslip". Task ID: 6431576
AI chat windows now display in front of other chat windows when opened on mobile devices. This prevents the AI assistant from being hidden behind existing conversations, making it easier for users to access it reliably.
Original PR description
AI chats opened on mobile views could appear behind other chats. This was inconsistent with the expected stacking behavior, where newly opened chats should appear on top of existing ones. To reproduce: * Open the chatter of any module. * Open the message composer in fullscreen mode. * Click the AI button. This commit increases the z-index of AI chats on mobile views so they are displayed on top of other chats. task-6412411 Forward-Port-Of: odoo/enterprise#128649 Forward-Port-Of: odoo/enterprise#128346
Social media users can now like stream posts without encountering permission errors. The update ensures the like action is handled safely in the background, improving reliability for Facebook and Twitter/X social workflows.
Original PR description
Bug === When a social user like a stream post, an access error is raised because he has no write access on it. Task-6425391 Forward-Port-Of: odoo/enterprise#128677 Forward-Port-Of: odoo/enterprise#125973
This fix prevents errors when users drag unscheduled planning slots onto the calendar after enabling scheduling options. It keeps planning workflows stable by ensuring the needed scheduling date information is provided and avoiding a crash when a date is missing.
Original PR description
Steps to reproduce: ------------------------- 1. Install `sale_planning` and `web_studio` with demo data. 2. Open the Planning calendar view. 3. Enable the "Scheduling" option from Studio and close…
Steps to reproduce:
-------------------------
1. Install `sale_planning` and `web_studio` with demo data.
2. Open the Planning calendar view.
3. Enable the "Scheduling" option from Studio and close it.
4. Drag an unscheduled slot onto the calendar.
Issues:
-----------
**Issue 1:**
```python
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 142, in write
self.assign_slot(vals)
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 159, in assign_slot
new_vals, tmp_sale_order_slots_to_plan, resource = slot._get_sale_order_slots_to_plan(vals, slot_vals_list_per_employee)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 228, in _get_sale_order_slots_to_plan
)._get_resource_work_info(vals, slot_vals_list_per_resource)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/enterprise/sale_planning/models/planning_slot.py", line 366, in _get_resource_work_info
assert self.env.context.get('default_end_datetime')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
```
**Issue 2:**
```python
UncaughtPromiseError > TypeError
Uncaught Promise > Cannot read properties of undefined (reading 'endOf')
TypeError: Cannot read properties of undefined (reading 'endOf')
```
Cause:
----------
Since commit [1ce0dc8,](https://github.com/odoo/odoo/commit/1ce0dc86f8ae52b21a5a889aacd1efce0e27c722) the scheduling/unscheduling logic has been moved to the generic calendar implementation. However, the generic scheduling flow does not provide the `default_end_datetime` context required by sale_planning. As a result, sale_planning raises an `AssertionError` while scheduling a slot.
Additionally, when no date is available, attempting to call `endOf()` raises a `TypeError`.
Solution:
------------
Introduce a generic scheduling context hook in the calendar model and override it in Planning to provide the `default_end_datetime context when scheduling a slot.
This restores the context expected by` sale_planning`, prevents the `AssertionError`, and avoids calling `endOf()` on an undefined date to resolve `TypeError`.
**Note:**
This issue has already been resolved in the later versions (saas-19.4) as part of the scheduling/unscheduling refactoring. This commit backports the minimal changes required to fix the issue in this version.
References: f82d073 & https://github.com/odoo-dev/odoo/commit/f0f7b342895734d2151c0c106940006e37a5fd86
Related community pr: https://github.com/odoo/odoo/pull/281178
opw-6442889
Forward-Port-Of: odoo/enterprise#127196The LinkedIn integration now handles cases where LinkedIn returns no account statistics during a refresh. This prevents an unnecessary crash and keeps social account data updates reliable even when LinkedIn has no metrics available.
Original PR description
Bug === When the LinkedIn API returns no statistics for the account, the refresh crashes. Task-6425391 Forward-Port-Of: odoo/enterprise#126326
Projects linked to both regular sales and rental orders now show the same orders when opening the Sales button as they count in the total. This avoids confusion and ensures rental-related sales are visible from the project view.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Observe the "Sales" stat button counts 2 Sales. 4. Click the stat button. Only the standard Sales Order is displayed. Issue --- In saas-18.4, the project Sales stat button calls action_view_sos without the from_embedded_action context key. As a result, _get_sale_orders_domain applies the non-rental filter by default, causing rental orders to be excluded from the action even though they are included in the displayed counter. Expected Behavior --- The Sales stat button should display all orders linked to the project, including both standard and rental orders, matching its total counter. Fix --- Return the base project domain unmodified when from_embedded_action is not set in the context. task-6140201 Forward-Port-Of: odoo/enterprise#128468 Forward-Port-Of: odoo/enterprise#121449
When a Shopee shop is re-authorized in Odoo using a different API account, the shop will now correctly switch to that account. This prevents shops from staying linked to an outdated account and reduces setup issues during re-authentication.
Original PR description
Context: when a user re-authenticate a shop, they might use different shopee.account (API key). Currently Odoo will not change the shopee.account when they re-auth with another shopee.account. Enable a shopee.shop switches to another shopee.account when we run `create_or_update_shop` function. Forward-Port-Of: odoo/enterprise#128469 Forward-Port-Of: odoo/enterprise#92446
This update records that GitHub user kshitij-nariya has signed Odoo's Individual Contributor License Agreement. It is an administrative legal update that allows their future contributions to be accepted and merged without CLA-related blocking.
Original PR description
Description of the issue/feature this PR addresses: Signed the Odoo Individual Contributor License Agreement to contribute to the Odoo repository. Current behaviour before PR: The CLA signature is missing for GitHub user `kshitij-nariya`, which will prevent future contributions from being accepted and merged. Desired behaviour after PR is merged: The CLA signature for `kshitij-nariya` is recorded in the repository, allowing future pull requests and contributions to be successfully merged. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282808
Manually merged Weblate translations to fix a merge conflict.
Original PR description
Manually merged Weblate translations to fix a merge conflict.