Tuesday, July 28, 2026
50 changes · saas-19.3
Enhancements to existing features
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#276628 Forward-Port-Of: odoo/odoo#251797
Original PR description
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#276628 Forward-Port-Of: odoo/odoo#251797
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
Resolved issues and error corrections
This fixes an internal test setup for Indian payroll so percentage calculations are checked using dedicated sample employee data. It helps prevent unrelated employee payroll values from affecting test results, without changing actual 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#124062 Forward-Port-Of: odoo/enterprise#121918
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It improves reliability for users working with cap table or equity transaction data by avoiding unexpected crashes during price calculation.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
This fix prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps ensure payroll data can continue to be handled smoothly without unexpected error screens for users.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
The trial balance report now handles load-more rows that have empty column data, preventing an error in the Colombian partner-grouped variant. This lets users continue expanding accounts and viewing additional report lines without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
This change adds a test to ensure financial reports handle changing domestic currency rates correctly. It helps prevent incorrect currency translation adjustment values when exchange rates fluctuate during the reporting period.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#123055
The Belgian minimum salary warning will now only appear for employees using Belgian payroll rules. This prevents irrelevant alerts from showing for employees in other countries, reducing confusion for HR users.
Original PR description
[FIX] l10n_be: fix min salary warning appearance in other l18n Bug reproduc: 1 - Install l10n_be_hr_payroll 2 - Go to some US employee, make its wage to 10. 3 - The warning "Annual salary is below 34654" will be there. Bug cause: 1 - The issue is created without controlling the country of the version Bug solution: 1 - Add Belgium country check to the issue creation task-6412374
This update fixes an unreliable automated tour test in Web Studio. It helps reduce false failures in validation pipelines, making releases and quality checks more dependable without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
This fix prevents an occasional timing issue from causing errors when the signing document viewer closes or reloads at just the wrong moment. It improves stability for Odoo Sign and helps keep automated validation runs clean 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
Vehicle references on invoice lines are no longer clickable while an invoice is still in draft. This keeps draft invoice behavior consistent with product links and helps prevent users from navigating to vehicle records before the invoice is finalized.
Original PR description
The vehicle under account on the invoice lines should not be clickable when the invoice is in draft. Only when it is posted, like the product. task-6385436 Forward-Port-Of: odoo/enterprise#124514
Fixed an issue where sales order information could be hidden on planning slot forms for companies using a single-company setup. This ensures users can consistently see and use the relevant sales order field regardless of company configuration.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673 Forward-Port-Of: odoo/enterprise#125712
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c
Original PR description
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c opw-6042550 Forward-Port-Of: odoo/odoo#275705 Forward-Port-Of: odoo/odoo#261468
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False a
Original PR description
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False and because that `Vat` field became reaonly and after recent fix `is_commercial_address` was set from `can_edit_vat` and validation done based on `can_edit_vat` before that `Vat` was editable if they have confirmed documents Fix: - Only make `Vat` readonly if Vat is set and is not individual address Forward-Port-Of: odoo/odoo#278233 Forward-Port-Of: odoo/odoo#277459
When inserting nodes, they are run through `node_to_insert_processors` to possibly handle some conversions - e.g. turning paragraphs into further list items within a list. However the `insertedNodes` returned by the `insert` method are actually the nodes that were initially requested to be added. This commit puts the nodes among the `insertedNodes` after they were potentially converted. task-6364282 Forward-Port-Of: odoo/odoo#277789
Original PR description
When inserting nodes, they are run through `node_to_insert_processors` to possibly handle some conversions - e.g. turning paragraphs into further list items within a list. However the `insertedNodes` returned by the `insert` method are actually the nodes that were initially requested to be added. This commit puts the nodes among the `insertedNodes` after they were potentially converted. task-6364282 Forward-Port-Of: odoo/odoo#277789
Issue: When changing from tracking inventory active > inactive > active the product would create 2 lines in the physical inventory. The first line would correspond to the first moment it was active and it wouldn't change. The second would be the difference between the new value we are trying to set minus the 1st line. Steps to reproduce: Create a product and with tracking selected on 'By Quantity', set 'Quantity On Hand' to 5 and save. Set tracking to blank (false) and save. Set tracking t
Original PR description
Issue: When changing from tracking inventory active > inactive > active the product would create 2 lines in the physical inventory. The first line would correspond to the first moment it was active and it wouldn't change. The second would be the difference between the new value we are trying to set minus the 1st line. Steps to reproduce: Create a product and with tracking selected on 'By Quantity', set 'Quantity On Hand' to 5 and save. Set tracking to blank (false) and save. Set tracking to 'By quantity' and set quantity on hand to 4. Refreshing the page will show 9 (5 + 4). Also, it will appear twice in physical inventory with quantities 5 and 4. Cause: Since the value is not reset when we change from 'By Quantity' to blank, the residual value stays and is not possible to change. Fix: Warning the user that he has to set to 0 the quantity of the product before he can change the tracking to blank. opw-6316788
`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
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
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
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
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-prDescription of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done inter-warehouse moves. This causes incorrect forecast values when a done stock move uses a UoM with a factor greater than 1. Current behavior before PR: When a done inter-warehouse move uses a UoM with factor > 1 (e.g. a box of 25 units), the forecast only subtracts the raw done quantity (e.g. 2 bo
Original PR description
Description of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done…
Description of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done inter-warehouse moves. This causes incorrect forecast values when a done stock move uses a UoM with a factor greater than 1. Current behavior before PR: When a done inter-warehouse move uses a UoM with factor > 1 (e.g. a box of 25 units), the forecast only subtracts the raw done quantity (e.g. 2 boxes) instead of the converted quantity in the product's base UoM (e.g. 50 units). This causes the forecast chart to show incorrect negative values before the move date. Steps to reporduce: - Create a storable product with base UoM = Units - Create a UoM "Box of 25" with factor = 25 in the Units category, and add it to the product's allowed UoMs - Create a second warehouse - Do an inventory adjustment of 800 units into warehouse 1 - Create an inter-warehouse transfer of 2 "Box of 25" (= 50 units) from warehouse 1 to warehouse 2 and validate it - Open the forecast chart for the product filtered to warehouse 1 Desired behavior after PR is merged: The forecast report for done inter-warehouse moves correctly converts the done quantity to the product's base UoM using the move's UoM factor, so the forecast chart shows accurate values regardless of the UoM used on the move. opw-6266745 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273797 Forward-Port-Of: odoo/odoo#271766
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and c
Original PR description
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module…
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and confirm the invoice. - Try to `Send To Tax Agency`. **Error:** `Node: <Natura t-if="line.tax_ids.l10n_it_exempt_reason" t-out="line.tax_ids.l10n_it_exempt_reason"/>` `ValueError: Expected singleton: account.tax(102, 3)` **Root Cause:** At [1], the code accesses `line.tax_ids.l10n_it_exempt_reason`, but when an invoice contains multiple taxes, causing an error. **Fix:** This commit prevents the error and ensures the user can send a simplified invoice by applying a fix similar to [2]. [1]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_simplified_template.xml#L14 [2]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_template.xml#L28-L181 Ticket [link](https://www.odoo.com/odoo/project.task/6354138) Ticket [link](https://www.odoo.com/odoo/project.task/6379377) opw-6354138 opw-6379377 Forward-Port-Of: odoo/odoo#278307 Forward-Port-Of: odoo/odoo#273823
Currently, the property value is not displayed on the Kanban card, even when the `Display in Cards` option is enabled. This PR ensures that if `Display in Cards` option is enabled for a property, its value is displayed on the corresponding equipment Kanban card. **Steps to reproduce:** - Install the Maintenance module. - Open `Equipment`. - Open an existing equipment record or create a new one and save it. - Click the actions (gear) menu from the equipment form view. - Select `Add Prop
Original PR description
Currently, the property value is not displayed on the Kanban card, even when the `Display in Cards` option is enabled. This PR ensures that if `Display in Cards` option is enabled for a property, its value is displayed on the corresponding equipment Kanban card. **Steps to reproduce:** - Install the Maintenance module. - Open `Equipment`. - Open an existing equipment record or create a new one and save it. - Click the actions (gear) menu from the equipment form view. - Select `Add Properties`. - Add a property and enable the `Display in Cards` option. Open the Kanban view. **Expected behavior:** The property value should be displayed on the Kanban card when the `Display in Cards` option is enabled. Issue: [#277479](https://github.com/odoo/odoo/issues/277479) Forward-Port-Of: odoo/odoo#277757
**Problem**: When a stock move has no quantity, the computation of the lot cost fails because it tries to divide by zero. **Fix**: Add a check to the ```move._get_valued_qty()``` to make sure it is not zero before performing the division. **Steps to reproduce:** 1. Create a product tracks quantity by lot, and valuation by Lot/Serial. 2. Assign a FIFO costing method category to it. 3. Update on hand quantity to 10 4. Reduce the on hand quantity to 5 and update to 10 again. 5. Go to t
Original PR description
**Problem**: When a stock move has no quantity, the computation of the lot cost fails because it tries to divide by zero. **Fix**: Add a check to the ```move._get_valued_qty()``` to make sure it is not zero before performing the division. **Steps to reproduce:** 1. Create a product tracks quantity by lot, and valuation by Lot/Serial. 2. Assign a FIFO costing method category to it. 3. Update on hand quantity to 10 4. Reduce the on hand quantity to 5 and update to 10 again. 5. Go to the in/out smart button and change the quantity of the most recent sml to 0. 6. Updating the on hand quantity to any larger number raises the error. **Notes**: This issue is created by the recent pr https://github.com/odoo/odoo/pull/273728. If a database has the same workflow before the commit, the error will be raised when checking the on hand quantity or trying to make a stock.picking of that product after checking out the commit. opw-6400941 Forward-Port-Of: odoo/odoo#277878
Only admin users have read access to the `payment.provider` model. Opening the PoS payment method form as a non-admin would raise an access error because the `online_payment_provider_ids` many2many field tries to fetch `payment.provider` records on form load. Grant read-only access on `payment.provider` to `group_pos_manager` so POS admins can use the field. Restrict the field's group in the form view to `point_of_sale.group_pos_manager,base.group_system` so it is not rendered for users witho
Original PR description
Only admin users have read access to the `payment.provider` model. Opening the PoS payment method form as a non-admin would raise an access error because the `online_payment_provider_ids` many2many field tries to fetch `payment.provider` records on form load. Grant read-only access on `payment.provider` to `group_pos_manager` so POS admins can use the field. Restrict the field's group in the form view to `point_of_sale.group_pos_manager,base.group_system` so it is not rendered for users without either role. opw-6208656 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276678 Forward-Port-Of: odoo/odoo#263837
We now search for the rates that can be used, instead of arbitrary filtering on the rates from the current main company, because - a branch could use the rates of its parents - company_id is not required on exchange rate objects ; when it's not set, it's for every company task-5953104 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.o
Original PR description
We now search for the rates that can be used, instead of arbitrary filtering on the rates from the current main company, because - a branch could use the rates of its parents - company_id is not required on exchange rate objects ; when it's not set, it's for every company task-5953104 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#259557
Problem: When computing inventory valuation or available quantities for a date in the past (using the context), the system calculates the past quantity by taking the current stock quants and rolling back the stock moves that occurred after the requested date. However, when the environment context specified an ownership filter (e.g., to calculate company-owned valuation), this filter was only being applied to the domain. The rollback domains for incoming and outgoing records remained comp
Original PR description
Problem: When computing inventory valuation or available quantities for a date in the past (using the context), the system calculates the past quantity by taking the current stock quants and rolling…
Problem: When computing inventory valuation or available quantities for a date in the past (using the context), the system calculates the past quantity by taking the current stock quants and rolling back the stock moves that occurred after the requested date. However, when the environment context specified an ownership filter (e.g., to calculate company-owned valuation), this filter was only being applied to the domain. The rollback domains for incoming and outgoing records remained completely open. As a result, the system would correctly see 0 company-owned current stock, but it would erroneously subtract incoming consigned stock moves from that balance. This resulted in an artificially negative past quantity and a negative inventory valuation for company-owned stock. Solution: This commit ensures the context is applied symmetrically by filtering the rollback moves via the field. The time-travel calculation will now only evaluate stock moves that match the queried ownership context. Steps to reproduce (runbot v19): - Consignment enabled - FIFO perpetual product w/ nonzero value 1. Create an inventory adjustment for an internal location, set the owner on the quant 2. Create a delivery for this product, but don't zero out all of the available stock 3. Go to Accounting > Review > Inventory Valuation, and set the At Date to something far in the past, before any move history in the db. The product's current on hand value will appear in ending stock, but negative. opw-6300582 Forward-Port-Of: odoo/odoo#274492 Forward-Port-Of: odoo/odoo#270409
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
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Configure a multi-company environment with a `Main Company` and a `Secondary Company` - Go to the setting enable Lots & Serial Numbers and switch into `Secondary Company` - Create a warehouse for the Secondary Company - In the Secondary Company, create a lot-tracked storable product - Create and validate a delivery for that product - Open the Traceability Report - Print the report Is
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Configure a multi-company environment with a `Main Company` and a `Secondary Company` - Go to the setting…
Version:
--------
- 18.0+
Steps to reproduce:
-------------------
- Install `stock` module
- Configure a multi-company environment with a `Main Company`
and a `Secondary Company`
- Go to the setting enable Lots & Serial Numbers and switch into
`Secondary Company`
- Create a warehouse for the Secondary Company
- In the Secondary Company, create a lot-tracked storable product
- Create and validate a delivery for that product
- Open the Traceability Report
- Print the report
Issue:
------
The report header always displays the Main Company, even though the
traceability report belongs entirely to the Secondary Company.
Cause:
------
https://github.com/odoo/odoo/blob/2d54db3ac0b6d807e580315e2633f3e2b10a700c/addons/stock/static/src/client_actions/stock_traceability_report_backend.xml#L9
Clicking Print calls onClickPrint(), which builds the PDF URL and
downloads it with download() (a plain XMLHttpRequest POST), landing on
the `type='http'` route `/stock/<output_format>/<report_name>`
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L125-L134
That controller calls stock.traceability.report.get_pdf() without ever setting
`company_id` in the rendering context.
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/stock/controllers/main.py#L23
Inside `get_pdf()`, the report header is rendered by passing an `rcontext`
dict to `web.internal_layout`.
That template resolves the company to display using the following priority:
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/addons/web/views/report_templates.xml#L805-L816
1. `company_id` — an explicit company record in the render context
2. `o.company_id` — the company of the document object `o`
3. `res_company` — the fallback, injected by `_render_template()` as
`self.env.company`
Because `get_pdf()` never sets `company_id` or `o` in `rcontext`, the
template always falls through to `res_company`.
https://github.com/odoo/odoo/blob/3bd6b10c3f9ad8d93062b6b46490500edb8c9697/odoo/addons/base/models/ir_actions_report.py#L770
This is populated by `ir.actions.report._render_template()`
as `self.env.company`, which resolves to the first company in
the user's `allowed_company_ids` list — typically the main company
regardless of which company owns the lot,
picking, or stock moves being printed.
As a result, the report content belongs to the secondary company while the
header always shows the main company.
Fix:
----
Resolve the company from the record on which the traceability report is
opened (using `active_model` and `active_id`) and pass it explicitly as
`company_id` when rendering the report.
`web.internal_layout` already gives precedence to an explicit
`company_id` over the default `res_company`, ensuring the report header
always displays the company that owns the traced record.
When the record has no company set, the header falls back to
`res_company`. Since the print request is a raw `type='http'` download
that never receives the company switcher's context, `user.context`
(holding `allowed_company_ids`) is now forwarded in the download POST
and merged into the environment by the controller - as done in
`web/controllers/report.py` - so the fallback resolves to the currently
active company instead of the user's default one.
<details>
<summary>Click here to see the results:</summary>
<p><strong>Before:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/7e3a5d65-9114-4bce-9139-a88cff7c261f" />
</div>
<p><strong>After:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/0a105f80-b6ae-400d-a787-fb8706d5f519" />
</div>
</details>
---
opw-6345446
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273595[1] added a bus channel for discuss categories. This can be done with or without any token. When the token is not passed, `verify_limited_field_access_token` is still called and crashes. When no token is provided, we should use category access rights instead and avoir verifying the token (which is `None`). [1]: https://github.com/odoo/odoo/pull/243131 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: ---
Original PR description
[1] added a bus channel for discuss categories. This can be done with or without any token. When the token is not passed, `verify_limited_field_access_token` is still called and crashes. When no token is provided, we should use category access rights instead and avoir verifying the token (which is `None`). [1]: https://github.com/odoo/odoo/pull/243131 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#276931
`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#278244When 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
When running test_catalog_price test, it checks for productUomFactor. However, when running single app tests, sometimes UOM is disabled, and productUomFactor won't be returned in that case. runbot-242515
Original PR description
When running test_catalog_price test, it checks for productUomFactor. However, when running single app tests, sometimes UOM is disabled, and productUomFactor won't be returned in that case. runbot-242515
# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job Position - Save # The problem If we go back to the contact, we can see it's name changed from X to Z. This is an expect behavior since : https://github.com/odoo/odoo/commit/c06aefa827bc00a14c9f8bd994d1831053cbf7af The issue lies in the fact that this change to the linked partner is not logged in
Original PR description
# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job…
# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job Position - Save # The problem If we go back to the contact, we can see it's name changed from X to Z. This is an expect behavior since : https://github.com/odoo/odoo/commit/c06aefa827bc00a14c9f8bd994d1831053cbf7af The issue lies in the fact that this change to the linked partner is not logged in the Applicant's form view. This may lead to contacts being unitentionally updated. # The cause `hr.applicant` inherits from 'mail.track.mixin', which correctly handles the logging in the chatter when editing an Applicant. However, the edition of the contact is triggered by an inverse function when creating the record, which is not handled by the inherited module : https://github.com/odoo/odoo/blob/af50cb24ac536e6afb14eee8221c69906191ba2b/addons/hr_recruitment/models/hr_applicant.py#L248-L253 # Proposed solution Use the `_track_record` method while tacking inspiration from : https://github.com/odoo/odoo/blob/3b5e4f558ccf9160e74e9e49ae324dd616241d61/addons/account/models/account_move_line.py#L2079 opw-6095671
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
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
#### Description of the issue this PR addresses: - Blockquotes currently display their border on the left side. #### Desired behavior after PR is merged: - Update the styling so the border is displayed on the right side for RTL content. task-6296519 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277057 Forward-Port-Of: odoo/odoo#269529
Original PR description
#### Description of the issue this PR addresses: - Blockquotes currently display their border on the left side. #### Desired behavior after PR is merged: - Update the styling so the border is displayed on the right side for RTL content. task-6296519 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277057 Forward-Port-Of: odoo/odoo#269529
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search
Original PR description
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search for the Pension Fund tax itself. Fiscally, the Natura belongs to the related VAT, not the Pension Fund. This incorrect domain caused the tax search to fail. The Pension Fund tax should not have a Natura setted. ### Reason to introduce the fix: To correctly apply Pension Fund taxes to exempt invoice lines. Ticket [link](https://www.odoo.com/odoo/project.task/6357133) opw-6357133 Forward-Port-Of: odoo/odoo#278478 Forward-Port-Of: odoo/odoo#275317
### 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
[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#277726Description 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
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a decimal duration such as 5.01 days. This is inconsistent with half-day time off types, which should consume time in half-day increments. **Steps to reproduce:** - Create an employee with a fully fixed duration-based schedule - Set morning and afternoon attendances to 3.36 hours for each weekday
Original PR description
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a…
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a decimal duration such as 5.01 days. This is inconsistent with half-day time off types, which should consume time in half-day increments. **Steps to reproduce:** - Create an employee with a fully fixed duration-based schedule - Set morning and afternoon attendances to 3.36 hours for each weekday - Create a time off type with duration type set to half-day - Create a time off request for the employee (e.g. Monday to Friday) - The computed duration is 5.01 days instead of 5 days **Cause:** For half-day time off types, `number_of_days` was taken from generic calendar interval computation. https://github.com/odoo/odoo/blob/19c0e59cc37c7671f13cbda1b2d4850a7731eade/addons/hr_holidays/models/hr_leave.py#L585-L593 On duration-based schedules, this computation returns day values rounded at 0.001 precision, so decimal drift (e.g. 5.01) can appear, Since no final rounding to half-day steps was applied, half-day requests could end with non-half-day values. **Solution:** Round computed durations for half-day time off types to the nearest half-day increment. opw-6215768 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278432 Forward-Port-Of: odoo/odoo#267726
## 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
The daily/monthly Inventory Valuation Closing cron currently skips companies using the Perpetual (real_time) valuation method, so the Periodic Valuation frequency setting has no effect for them. The intent of the feature is to keep the inventory valuation continuously updated (e.g. goods received not yet invoiced) whatever the valuation method, so the cron should also post the closing entries for perpetual companies. Remove the real_time exclusion from the cron domain so the configured frequency
Original PR description
The daily/monthly Inventory Valuation Closing cron currently skips companies using the Perpetual (real_time) valuation method, so the Periodic Valuation frequency setting has no effect for them. The intent of the feature is to keep the inventory valuation continuously updated (e.g. goods received not yet invoiced) whatever the valuation method, so the cron should also post the closing entries for perpetual companies. Remove the real_time exclusion from the cron domain so the configured frequency applies to all companies, and skip companies where the closing raises a UserError (e.g. missing valuation journal or account) so one misconfigured company cannot block the cron. Forward-Port-Of: odoo/odoo#277820 Forward-Port-Of: odoo/odoo#276990
Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_p
Original PR description
Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_project_id` condition and enforce only `has_template_ancestor = True` in the domain, ensuring that only actual template tasks are shown. task-5966601 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260624
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rat
Original PR description
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes…
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rather than the savable selectors resource. As a result, elements which had the `o_not_editable` class, such as job location, did not have `o_savable` added to them. These elements were excluded from the builder's dirty-tracking for save. Therefore, editing the location didn't mark the element as changed and saving to drop the update. Fix: Remove `o_not_editable` from the location element on plugin setup so the field is now editable and savable through the builder option. This surfaced a second issue: when the location was set to "Remote", the element's content could be directly editable inline. Saving it that way disconnected the content from the job location field. This was fixed by adjusting the selector that determines when a many2one's content is editable inline. The result is the "Remote" case is handled consistently as changing to any other location. [1]: https://github.com/odoo/odoo/commit/f3c119dd034b4c3df9f392b0cdc66a1141662c25 Task-6311200 Forward-Port-Of: odoo/odoo#274731
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
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max
Original PR description
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt…
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max width, so it gets cut when the receipt is narrow. The fix ------- Render it at 400 px, and add `max-width: 100%` so it is not cut on a narrow receipt. opw-6399766 Before <img width="647" height="1036" alt="image" src="https://github.com/user-attachments/assets/6bcb8526-71a8-4d9f-8372-219959416214" /> After <img width="649" height="1031" alt="image" src="https://github.com/user-attachments/assets/70f5fdb5-ba71-4fbe-8f03-ef0a1b29be2e" /> Forward-Port-Of: odoo/odoo#278499 Forward-Port-Of: odoo/odoo#277813