Daily updates from Odoo
Tuesday, July 28, 2026
45 changes · saas-19.4
Enhancements to existing features
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Chan
Original PR description
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Change Password URL specification by exposing a public route that redirects to `/web/reset_password`. Reference: https://wicg.github.io/change-password-url/ --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277575
In some cases, you want to redirect a record with ModelConverter, whatever the slug value. E.g. /shop/old-name-1 => /shop/alt-product-10 /shop/new-name-1 => /shop/alt-product-10 /fr/shop/nom-1 => /shop/alternatif-product-10 /de/shop/produktname-1 => /de/shop/produktname-10 In this case, adding only one redirect /shop/1 => /shop/10 covers the need to support all the translated slugs and the old name that we remember. On odoo.com we have this need e.g. when we archive a
Original PR description
In some cases, you want to redirect a record with ModelConverter, whatever the slug value.
E.g. /shop/old-name-1 => /shop/alt-product-10
/shop/new-name-1 => /shop/alt-product-10
/fr/shop/nom-1 => /shop/alternatif-product-10
/de/shop/produktname-1 => /de/shop/produktname-10
In this case, adding only one redirect /shop/1 => /shop/10 covers the need to support all the translated slugs and the old name that we remember.
On odoo.com we have this need e.g. when we archive a Job Position, we create a redirect, but in some cases the job position is translated or has been renamed and we don't remember all the old urls. With this change, we will be able to redirect all old urls, translated urls, ... with only one redirect.
/jobs/10 -> /explore-more-opportunities-with-us
task-6391567
Forward-Port-Of: odoo/odoo#276515We now avoid sharing logs to the database in favor of logging using sentry. task-6329137
Original PR description
We now avoid sharing logs to the database in favor of logging using sentry. task-6329137
Resolved issues and error corrections
This fix prevents branch-only users in Ecuadorian companies from being blocked when creating customer invoices. It keeps invoice creation working in parent-child company setups by reading the needed country information without requiring access to the parent company.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This fix updates an internal tracking hook in Planning Field Service so it matches the latest mail activity logging behavior. It helps ensure status changes continue to be recorded correctly without changing how users work.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This change fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep release validation stable and reduces false alarms during quality checks, without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Belgian payroll now correctly assigns an employee's DMFA work location when a matching work address is used on a new contract version. This helps ensure payroll location and working region information is accurate without requiring a manual address update.
Original PR description
After creating a dmfa location unit, creating a new version for an employee with the matching address_id should have self.l10n_be_location_unit and self.l10n_be_working_region set to the new value. For now, the field is only recomputed when updating address_id field.
- Steps to reproduce:
- With l10n_be_hr_payroll installed, create an employee in a BE company.
- Create a dmfa work location for the employee work address.
- Create a new contract for that employee.
- Employee l10n_be_location_unit field is still False.
- Cause: the compute method is triggered only on address_id field update.
- Solution: add `address_id.l10n_be_dmfa_location_unit_ids` to the depends decorator of the compute method.
Task: 6360653Payroll module upgrades are now protected from a crash caused by warning checks running too early. This helps businesses complete payroll updates more reliably, especially when optional payroll features are installed.
Original PR description
task-6345962
This fix updates an internal payroll test to use its own employee data instead of reusing an employee with existing payroll values. It helps keep India payroll percentage checks accurate and stable without changing payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124330 Forward-Port-Of: odoo/enterprise#121918
Mexican electronic invoicing now correctly updates the Tax Object field when a product’s unit price is added after an invoice was first saved. This helps keep invoices accurate and reduces manual corrections for compliance-related tax information.
Original PR description
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a…
**Steps to reproduce the issue:** - Install the l10n_mx_edi module. - Open the Accounting app and go to Customers → Invoices. - From the invoice line, make the Tax Object field visible. - Create a new invoice and add a product that has no Unit Price. - Save the invoice. - Edit the same invoice, set a Unit Price for the product, and save it again. - Issue: The Tax Object field is not automatically set after the Unit Price is added. **Description:** - In our standard code, there is a condition that skips computing the Tax Object when the Unit Price is [0](https://github.com/odoo/enterprise/blob/615a5f756d708db95e22cdbdd6e7aca72ac769ec/l10n_mx_edi/models/account_move.py#L988). This is the expected behavior. - However, after setting a Unit Price on the product, the Tax Object is not recomputed, so it remains unset. - To resolve this issue, I added price_unit to the @api.depends decorator so that the Tax Object is recomputed whenever the Unit Price changes. **Reference videos:** Before the fix: [screen-capture (2).webm](https://github.com/user-attachments/assets/c1162fd9-52b8-4a8c-9ac2-39cf2ca3ad69) After the fix: [screen-capture (1).webm](https://github.com/user-attachments/assets/1c05dc34-6778-487a-9bfc-635cf652e670) OPW -6305080 UPG - 4268848 Forward-Port-Of: odoo/enterprise#125530 Forward-Port-Of: odoo/enterprise#123009
The Twitter social integration now disables the reply option for tweets where replies are not permitted by Twitter, such as tweets that do not mention the company account or quote one of its tweets. This helps prevent failed or inappropriate automated responses and keeps user actions aligned with Twitter rules.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
This update prevents occasional errors when a signing PDF preview is closed or detached at just the wrong moment. It improves the reliability of automated checks and helps keep the Sign app stable without changing user-facing behavior.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This update corrects Swedish ISO 20022 payment files so they match Swedbank's required identifiers and scheme values. It reduces the risk of bank payment files being rejected and also updates Swedish address formatting ahead of upcoming structured address requirements.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125676
Forward-Port-Of: odoo/enterprise#122119This fix prevents the timesheet assistant from crashing when away-time activity is processed without an expected unmatched group. Users can continue reviewing and categorizing time entries without interruption.
Original PR description
Before this commit, when the unmatched group is not found in events before processing afk event, a traceback occurs saying `Cannot read properties of undefined (reading 'Away (afk status 1)')` This commit moves the code checking the group key exists in `this.state.grouped` after processing afk event and before adding the afk event in unmatched group. Forward-Port-Of: odoo/enterprise#124072 Forward-Port-Of: odoo/enterprise#123452
Resetting a tax return now only removes accounting entries that were created for recoverable amounts from earlier tax returns. This prevents invoices or other reconciled entries from being accidentally deleted, protecting accounting records from unintended data loss.
Original PR description
Issue: Moves having a line reconciled to a tax return are unlinked if the tax return is reset. Steps to reproduce: - Set the tax account as reconcilable - Create an invoice for previous month and confirm it - Create a tax return for the previous month - Reconcile one of the invoice tax line to the tax return closing move. - Remove the lock date - Reset the tax return Current behavior: - all moves reconciled with the tax return are unlinked Expected behavior: - only moves comming from recoverable amount of previous tax returns should be unlinked opw-6370289 Forward-Port-Of: odoo/enterprise#123947
Fixes several issues affecting cumulative translation adjustment lines in financial reports. Trial balance and general ledger outputs now better respect horizontal groups, search filters, and fiscal-year dates, reducing the risk of confusing or incorrect report totals.
Original PR description
The engine for the cumulative translation adjustment line was fully overriding the forced options, but this key might already be present in the options, for example, when using horizontal groups. task-6418960 Forward-Port-Of: odoo/enterprise#124108
Fixed an issue that could prevent Belgian payroll users from opening the Payroll dashboard when multiple CP200 employees had recently updated contracts. The minimum wage warning now evaluates employees correctly, helping payroll teams access their dashboard reliably.
Original PR description
Opening the Payroll dashboard may crashes with an error: - Have a Belgian company with 2 or more CP200 employees having active contracts - Create or modify a contract for at least 2 of them (this marks l10n_be_computed_seniority_years as dirty for the batch) - Open the Payroll dashboard, the "Employees Under Minimum Wage" warning evaluation crashes In _compute_l10n_be_computed_seniority, the for version in cp200_versions loop was incorrectly referencing self instead of version. Since self is the full batch recordset, self.employee_id returns a multi-record set, causing ensure_one() to fail inside _get_first_version_date. task-6358718
When a Colombian electronic invoice is issued from a branch, the XML now uses the parent company's legal name instead of the branch name. This helps DIAN correctly match the invoice to the company's tax ID and reduces the risk of rejected electronic invoices.
Original PR description
The correct behavior should be to use the original company name in this specific XML tag For the DIAN, branch names will not be recognized as related to the NIT. So, when sending electronic invoices from a branch, the XML should use the name of the parent company of that branch. Ticket [link](https://www.odoo.com/odoo/project.task/6074280) opw-6074280 Forward-Port-Of: odoo/enterprise#125383 Forward-Port-Of: odoo/enterprise#115494
When equipment is manually removed from a field service shift, later edits such as changing shift times or signing in no longer add it back automatically. This helps teams keep shift equipment lists accurate while still refreshing the list when the customer is changed.
Original PR description
Issue: When a user manually removes a specific equipment (SN) from a shift's list, editing the shift times or signing in reloads the entire list, bringing the deleted equipment back. Solution: Skip reassignment if the currently selected lots (`._origin`) are a valid subset of the customer's total equipment. This preserves manual deletions while still correctly updating the list if the customer is completely changed. Task: 6346404
Spanish VAT record book exports now include taxable accounting entries created outside standard invoices and bills, such as Point of Sale session closures. This helps businesses produce more complete VAT records and reduces the risk of missing taxable POS activity in compliance reports.
Original PR description
Currently, the Spanish VAT record books (Libros Registro de IVA) only include move types associated with invoices and bills. However, miscellaneous entries (type 'entry'), such as those generated by the Point of Sale session closures or manual liquidations, also carry tax obligations and must be reflected in these reports. Steps to reproduce: - Open a POS Session - Create an order, pay and close session - Go to Accouting > Reporting > Tax report - Select Generic Tax report - Print "VAT record Books" Issue: Only invoices and bills are visible in the excel file, and not the entry generated from point of sale. However, movements that are not related to invoices should be included in the VAT books. opw-5862529 Forward-Port-Of: odoo/enterprise#125631 Forward-Port-Of: odoo/enterprise#113681
Belgian payroll withholding tax reductions now apply correctly for disabled employees, disabled spouses, and spouses with low or no income, even when there are no dependent juniors or seniors. The update helps ensure affected employees receive the correct payroll tax treatment and clarifies spouse fiscal threshold wording.
Original PR description
Prior to this commit, the reductions for disabled employees, disabled spouse, and spouse with low or no income did not apply if the employee did not have any depenedent juniors or seniors. This commit fixes that, by removing the unneeded condition, and applying the reductions for those employees. This commit also updates the text for the thresholds of the spouse's fiscal situation. task-6384236 task-6320606 Forward-Port-Of: odoo/enterprise#124803
Marketing campaigns no longer crash when a user clears the Target field while editing a campaign. This keeps campaign setup stable and avoids an unexpected error during normal data entry.
Original PR description
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` >…
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` > `Campaigns`. - Create a `new campaign` and clear the `Target` field. `KeyError: False` After the recent commit that added the recipients_count field and its computation [1], when the user removes model_id(Target), model_name is set to False [2]. The domain is then updated by a compute method, which triggers the computation of recipients_count. Since the computation only checks whether domain is set and does not verify that model_name is available, it attempts to access the model using model_name, raising the error [3]. This commit ensures that, when computing the recipient count, it also checks that model_name is set. Since model_id is a required field, once it is set, the recipient count is computed correctly based on the domain and model_name. [recent commit]: https://github.com/odoo/enterprise/commit/5485e8eaa7636c7dd0b305b4e26fb772aff6d030 [1]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L43 [2]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L33 [3]- https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L146-L148 sentry-7612724367
The timesheet assistant now lets long description fields expand so users can read the full content instead of seeing it cut off. This makes reviewing and editing timesheet entries clearer and reduces the chance of missing important details.
Original PR description
- changed the description field to expand dynamically to display long descriptions in full instead of truncating them in the assistant Task-6348575 Forward-Port-Of: odoo/enterprise#124806 Forward-Port-Of: odoo/enterprise#123428
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solu
Original PR description
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, temporary `sudo()` usage is required in specific places. opw-6087460 Forward-Port-Of: odoo/odoo#259299
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
Original PR description
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
`t-key` are automatically added to `t-for` elements in templates, but if someone defines `t-key` himself, the converter is supposed to keep it as is. Before this fix: -`t-key` is kept but a closing tag (`>`) is added every iteration. After this fix: -`t-key` is correctly kept, nothing added in addition. Forward-Port-Of: odoo/odoo#276858
Original PR description
`t-key` are automatically added to `t-for` elements in templates, but if someone defines `t-key` himself, the converter is supposed to keep it as is. Before this fix: -`t-key` is kept but a closing tag (`>`) is added every iteration. After this fix: -`t-key` is correctly kept, nothing added in addition. Forward-Port-Of: odoo/odoo#276858
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so by negating `balance` and `amount_currency` on every prepared line, but leaves `tax_base_amount` on tax lines untouched. As a result the reversal move ends up with tax lines whose `balance` sign is flipped relative to the source order while `tax_base_amount` keeps the source sign, breaking the in
Original PR description
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so…
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so by negating `balance` and `amount_currency` on every prepared line, but leaves `tax_base_amount` on tax lines untouched. As a result the reversal move ends up with tax lines whose `balance` sign is flipped relative to the source order while `tax_base_amount` keeps the source sign, breaking the invariant `sign(balance) == sign(tax_base_amount)` that holds for every other correctly-generated tax line in the system. Downstream, any report reading `tax_base_amount` directly (Audit view from the Tax Report, Journal Items XLSX export, custom exports) shows a base amount signed for the wrong direction alongside a debit/credit of the opposite sign, which is confusing and, for tax returns computed from `tax_base_amount`, incorrect. Negate `tax_base_amount` alongside `balance` and `amount_currency` so the reversal move stays internally consistent. opw-5975658 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#276534
A deferred toolbar update can still fire after the ToolbarPlugin has been destroyed. The global "mouseup" handler re-arms `updateToolbar` through a raw setTimeout that is not cancelled by `destroy`, so `_updateToolbar` runs on a plugin whose editable document has been detached. At that point `this.document.defaultView` is null and `getFilteredTargetedNodes` crashes with: TypeError: Cannot read properties of null (reading 'getComputedStyle') Cancelling the debounced updates in `destroy`
Original PR description
A deferred toolbar update can still fire after the ToolbarPlugin has been destroyed. The global "mouseup" handler re-arms `updateToolbar` through a raw setTimeout that is not cancelled by `destroy`, so `_updateToolbar` runs on a plugin whose editable document has been detached. At that point `this.document.defaultView` is null and `getFilteredTargetedNodes` crashes with:
TypeError: Cannot read properties of null (reading 'getComputedStyle')
Cancelling the debounced updates in `destroy` is not enough: `cancel()` only clears the currently pending timer, it does not disable the debounced function, so the post-destroy `updateToolbar()` call re-schedules it.
Guard `_updateToolbar` with the plugin's `isDestroyed` flag instead, which covers every deferred entry point.
Forward-Port-Of: odoo/odoo#278244**Steps to reproduce,** - log in as admin, handle notifications 'in odoo' - have a message related to a task and read it - reload the page, go to Discuss > History - find the read message mark it as unread **Current behavior before PR**, The message returned to the systray, but it lost its specific module icon and task priority. **Cause**, Since [1](https://github.com/odoo/odoo/pull/247765), inbox/systray fields are only sent when needed, but this missed the unread messages flow, s
Original PR description
**Steps to reproduce,** - log in as admin, handle notifications 'in odoo' - have a message related to a task and read it - reload the page, go to Discuss > History - find the read message mark it as unread **Current behavior before PR**, The message returned to the systray, but it lost its specific module icon and task priority. **Cause**, Since [1](https://github.com/odoo/odoo/pull/247765), inbox/systray fields are only sent when needed, but this missed the unread messages flow, so the server never sent them. **Desired behavior after PR is merged**, The message returned to the systray correctly shows the module icon and task priority. task-6188886 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278517 Forward-Port-Of: odoo/odoo#266322
Before this commit, opening the new working schedule wizard with a variable calendar type and adding the first time window would freeze the save discard and close buttons because the calendar widget rebuilt its domain and context on every render, causing the search model to reload twice at once and one reload would hang forever. After this commit, the calendar widget reuses the same domain and context as long as the record id stays the same, so the reload only happens once and the buttons wor
Original PR description
Before this commit, opening the new working schedule wizard with a variable calendar type and adding the first time window would freeze the save discard and close buttons because the calendar widget rebuilt its domain and context on every render, causing the search model to reload twice at once and one reload would hang forever. After this commit, the calendar widget reuses the same domain and context as long as the record id stays the same, so the reload only happens once and the buttons work normally after adding a time window. task-6356678
Purpose ======= Fix the expected/recurring revenues and probability fields display in the crm opportunity and lead desktop form views. In mobile views, the display is different, there's nothing to be fixed. Specification ============= The revenue fields should have a larger width to display higher numbers. In this optic, increasing the 'o_input_...ch' utility class possible sizes. The "at" word shouldn't be visible if the type is 'lead' and there's no recurring revenues. Also fixing som
Original PR description
Purpose ======= Fix the expected/recurring revenues and probability fields display in the crm opportunity and lead desktop form views. In mobile views, the display is different, there's nothing to be fixed. Specification ============= The revenue fields should have a larger width to display higher numbers. In this optic, increasing the 'o_input_...ch' utility class possible sizes. The "at" word shouldn't be visible if the type is 'lead' and there's no recurring revenues. Also fixing some spacings issues. Task-6387897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276195
### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longe
Original PR description
### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longer match and a danger warning is displayed above the report ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: A1 and T1_base, 100 of tax: T1_taxe) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, a red warning is raised: Sum of 08+09+9B+10+11+T1->T7 is not equal to sum of A1+A2+A3+B2+B3+B4 opw-6357703 Forward-Port-Of: odoo/odoo#276446
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO,
Original PR description
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get…
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO, click on "Bill matching" button - Select the 4 lines and click on the "Match" button -> On the purchase order, first line has qty_invoiced == 2 and the second one 0 -> On the bill, there is an additional line with 0 quantity This is because we only match the first order line in case of having more than one line with the same product. Then we add the remaining order lines to the bill. With this commit we match each line that need to be matched and we add lines to the bill only if all order lines have been invoiced. opw-6279755 Forward-Port-Of: odoo/odoo#277067 Forward-Port-Of: odoo/odoo#269496
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a
Original PR description
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which…
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a rounding line" and precision 1.00. - Make Company A the active company in the company switcher. - Set the cash rounding's profit and loss accounts to Company A accounts. - Switch the active company to Company B. - Set the cash rounding's profit and loss accounts to Company B accounts. - Make Company A the active company again, keeping both companies active. - Create a customer invoice for Company B. - Add one invoice line whose total is not a multiple of the rounding precision. - Set the invoice's cash rounding to the one above. > Adding the rounding line raises a cross-company UserError: the company-dependent account is resolved against Company A while the invoice belongs to Company B. Desired behavior after PR is merged: The rounding line resolves the company-dependent profit/loss account against the invoice's own company, so the rounding line always uses that company's account and no cross-company error is raised. Covered by the added test TestAccountMoveCashRoundingMultiCompany. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278401 Forward-Port-Of: odoo/odoo#273410
Helpers for the enterprise PR opw-5862529 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278518 Forward-Port-Of: odoo/odoo#270624
Original PR description
Helpers for the enterprise PR opw-5862529 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278518 Forward-Port-Of: odoo/odoo#270624
[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 - Select US jobs and search for the remote job. 4 - All countries filter is readonly and it is not pressable. Bug cause: 1 - Check is done with jobs value 1.1 - If no matching, readonly button is displayed. Bug solution: 1 - count_per_filter is used instead of
Original PR description
[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 -…
[FIX] website_hr_recruitment: fix country filter
Bug reproduction:
1 - Recruitment, you need to have 1 remote and 1 US jobs at least.
2 - Go to job page in website, activate country filter.
3 - Select US jobs and search for the remote job.
4 - All countries filter is readonly and it is not pressable.
Bug cause:
1 - Check is done with jobs value
1.1 - If no matching, readonly button is displayed.
Bug solution:
1 - count_per_filter is used instead of jobs
1.1 - Even there are matchings for other countries, it shows.
2 - Also, searched keyword is added to filter url
2.1 - When there is search in other country and we click to it:
2.2 - The searched keyword will be still there.
task-6284436
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#277726## Steps to Reproduce: _(cryptography version > 43.0.0)_ 1. Install the `l10n_sa_edi` module. 2. Switch to SA Company. 3. Set the company name to an Arabic string between 32 and 64 characters. (e.g; `مجموعة النخبة العالمية للاستشارات الفنية`) 5. Accounting > Configuration > Journals. 6. Open a Sales type journal. 7. Click "Re-onboard" in the ZATCA tab. 8. Enter an OTP and click "Request". ## Error: `ValueError: Attribute's length must be >= 1 and <= 64, but it was 98` ## Caus
Original PR description
## Steps to Reproduce: _(cryptography version > 43.0.0)_ 1. Install the `l10n_sa_edi` module. 2. Switch to SA Company. 3. Set the company name to an Arabic string between 32 and 64 characters. (e.g;…
## Steps to Reproduce: _(cryptography version > 43.0.0)_
1. Install the `l10n_sa_edi` module.
2. Switch to SA Company.
3. Set the company name to an Arabic string between 32 and 64 characters.
(e.g; `مجموعة النخبة العالمية للاستشارات الفنية`)
5. Accounting > Configuration > Journals.
6. Open a Sales type journal.
7. Click "Re-onboard" in the ZATCA tab.
8. Enter an OTP and click "Request".
## Error:
`ValueError: Attribute's length must be >= 1 and <= 64, but it was 98`
## Cause:
The CSR validation checks the length of characters, if combined common_name (or other fields) are less than 64 characters, it passes the condition. - [1] But the cryptography library validates UTF-8 byte length for string values. Arabic characters take 2 bytes in UTF-8, causing the byte length to exceed the 64-byte limit enforced by the cryptography.
**Note:**
Starting with cryptography version 43.0.0, the library enforces the UTF-8 byte length limit for CSR string values during certificate creation. (Ref: https://github.com/pyca/cryptography/pull/11201)
## Fix:
Validate the UTF-8 encoded byte length instead of the character length.
[1] - https://github.com/odoo/odoo/blob/a66fedcaf555660e484a2becc49a9b7e602f5924/addons/l10n_sa_edi/models/certificate.py#L92
sentry-7608376856
Forward-Port-Of: odoo/odoo#277822
Forward-Port-Of: odoo/odoo#276861**Problem:** For an hour-based time off allocation, changing the employee's working schedule leaves the allocation duration (in days) stale, so the balance shown on the Time Off dashboard becomes wrong. **Steps to reproduce:** 1. Give an employee a working schedule of 8 hours/day. 2. Create an hour-based allocation (time off type with Request Unit = Hours) granting e.g. 8 hours (1 day). 3. Change the employee's working schedule to one with a different Hours per Day (e.g. 4 hours/day). 4.
Original PR description
**Problem:** For an hour-based time off allocation, changing the employee's working schedule leaves the allocation duration (in days) stale, so the balance shown on the Time Off dashboard becomes…
**Problem:** For an hour-based time off allocation, changing the employee's working schedule leaves the allocation duration (in days) stale, so the balance shown on the Time Off dashboard becomes wrong. **Steps to reproduce:** 1. Give an employee a working schedule of 8 hours/day. 2. Create an hour-based allocation (time off type with Request Unit = Hours) granting e.g. 8 hours (1 day). 3. Change the employee's working schedule to one with a different Hours per Day (e.g. 4 hours/day). 4. Check the allocation / the Time Off dashboard balance. **Current behavior:** number_of_days stays at its old value (1), so the balance is recomputed as 1 day x 4 hours = 4 hours instead of the 8 hours actually accrued. **Expected behavior:** The accrued hours stay constant; the duration in days follows the new schedule (8 hours / 4 hours-per-day = 2 days). **Cause of the issue:** `number_of_days` and `number_of_hours_display` compute from each other (`number_of_days = number_of_hours_display / hours_per_day` and `number_of_hours_display = number_of_days * hours_per_day`), forming a dependency cycle, and neither depends on the employee's working schedule. So a schedule change never recomputes either field. Adding the schedule to `_compute_number_of_days`' depends does not help: because of the cycle it recomputes `number_of_hours_display` from the stale `number_of_days` first, which silently destroys the accrued hours. **Fix:** When the employee's working schedule changes, the accrued hours are the quantity that must be preserved, so the duration is recomputed explicitly from the still-stored `number_of_hours_display` (setting `number_of_days` first, exactly as a manual `_compute_number_of_days()` does). Driving the order by hand is necessary because the cyclic compute graph cannot guarantee `number_of_days` is computed before `number_of_hours_display`. opw-6276242 Forward-Port-Of: odoo/odoo#270129
Account codes are no longer required on accounts. The import template that is given in accounting settings > import still indicates that the code is mandatory. This commit removes this mandatory indicator from the template. task-6313017 Forward-Port-Of: odoo/odoo#278600
Original PR description
Account codes are no longer required on accounts. The import template that is given in accounting settings > import still indicates that the code is mandatory. This commit removes this mandatory indicator from the template. task-6313017 Forward-Port-Of: odoo/odoo#278600
Before this commit, opening demo data CRM "Modern Open Space" and clicking on "Send message" of chatter would lead to a crash in debug mode. This happens because RecipientTags receive props `resId: false` that doesn't follow props validation that expects a number. This is a change from owl3 where the type of props was not validated but was restricted to `number`, although there were genuine cases of `false` value. This commit adds `false` as an expected value of `resId` props of `Recipi
Original PR description
Before this commit, opening demo data CRM "Modern Open Space" and clicking on "Send message" of chatter would lead to a crash in debug mode. This happens because RecipientTags receive props `resId: false` that doesn't follow props validation that expects a number. This is a change from owl3 where the type of props was not validated but was restricted to `number`, although there were genuine cases of `false` value. This commit adds `false` as an expected value of `resId` props of `RecipientTag`. Task-6424706
A `<video>` element with an active srcObject is exempt from normal DOM garbage collection by the browser, even once detached and dereferenced, so the component stays retained through its loadedmetadata listener [1]. This showed up as ComponentNode instances piling up in memory snapshots across the call hoot test suite. Clear srcObject (and reload) on unmount to let the element, and everything it retains, be garbage collected. [1] https://html.spec.whatwg.org/multipage/media.html#best-pract
Original PR description
A `<video>` element with an active srcObject is exempt from normal DOM garbage collection by the browser, even once detached and dereferenced, so the component stays retained through its loadedmetadata listener [1]. This showed up as ComponentNode instances piling up in memory snapshots across the call hoot test suite. Clear srcObject (and reload) on unmount to let the element, and everything it retains, be garbage collected. [1] https://html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements 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
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303 Forward-Port-Of: odoo/odoo#278423
Original PR description
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303 Forward-Port-Of: odoo/odoo#278423
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo. That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on th
Original PR description
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are…
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo.
That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on that field (in `Field.__get__`) is done on the non-sudo environment.
This is visible on `res.users.main_user_id`, an inherited field `res.partner.main_user_id` (compute_sudo=False, depends_context('uid')). The compute succeeds, but the resulting value is written into the sudo cache instead of the caller's cache, so the non-sudo cache check right after considers it missing:
```py
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py", line 1827, in __get__
raise ValueError(f"Compute method failed to assign {missing_recs}.{self.name}")
ValueError: Compute method failed to assign res.users(2,).main_user_id
```
Confirmed in pdb: the id is missing from the plain cache but present in the sudo one:
```py
> /home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py(1823)__get__()
-> missing_recs_ids = tuple(self._cache_missing_ids(recs))
(Pdb) tuple(self._cache_missing_ids(recs))
(2,)
(Pdb) tuple(self._cache_missing_ids(recs.sudo()))
()
```
Steps to reproduce:
- in saas~19.3, open the Users list view
- using Studio, add the `main_user_id` field to the list view
- the view fails to load with: "The requested change caused an error in the view. It could be because a field was deleted, but still used somewhere else."
- The error in logs is the `ValueError` mentioned above
Restrict the forced `sudo()` to x2m fields, which is what the original comment describes and what actually needs it, and let many2one related fields honor their own `compute_sudo` like every other compute does.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278651## Short fix summary: `res.partner.company_registry` was removed by a core refactor (6f8c2526a00d), which broke `l10n_ge`'s demo data install since `demo/demo_company.xml` still set that field. This drops the field, and adds two demo customer partners (individual + business TIN format) so there's actually someone to invoice in a demo/test flow. no-task-id I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
## Short fix summary: `res.partner.company_registry` was removed by a core refactor (6f8c2526a00d), which broke `l10n_ge`'s demo data install since `demo/demo_company.xml` still set that field. This drops the field, and adds two demo customer partners (individual + business TIN format) so there's actually someone to invoice in a demo/test flow. no-task-id I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021