Daily updates from Odoo
Monday, August 10, 2026
36 changes · saas-19.1
Enhancements to existing features
All signers can now choose whether to add a frame when adopting their signature, not just internal Odoo users. The public signing dialog also has clearer borders around key fields and buttons, making it easier for customers and external recipients to complete documents confidently.
Original PR description
Version: 19.0 Before this PR: The 'Frame' checkbox in the 'Adopt Your Signature' dialog was only shown to internal Odoo users (users with the `base.group_user` group).Also, on the public signing page, the Full Name input, the Frame checkbox and the Auto/Draw/Load buttons had no visible border After this PR: The 'Frame' checkbox is now rendered for every signer in the 'Adopt Your Signature' dialog. The Full Name input, Frame checkbox and Auto/Draw/Load buttons now have a visible border. Taskid-4610728 Forward-Port-Of: odoo/enterprise#126789
Belgian payroll now includes the upcoming fiscal employment bonus rate changes for low-wage workers from August 2026 and the general rate increase planned for 2028. This helps payroll calculations stay aligned with future Belgian tax rules without manual rate adjustments.
Original PR description
Starting from August 2026: - The increased fiscal rate for low-wage workers (Volet B) rises from 52.54% to 63% (and to 72% in 2028). - The general fiscal rate (Volet A) rises from 33.14% to 35% starting in 2028. This adds new rule parameters for the fiscal rates and updates computation logic to apply these rates Task-6438319 Forward-Port-Of: odoo/enterprise#126713
…h lookup _search_phone_mobile_search previously searched only raw number fields returned by _phone_get_number_fields (e.g. mobile, phone). E164-normalized phone_sanitized was ignored, so searching by a sanitized value could miss records that had no match on the raw fields. This commit: - Extracts _phone_get_searchable_fields() so that both init() and _search_phone_mobile_search build the same searchable field list, appending phone_sanitized alongside mobile/phone when available. - Add
Original PR description
…h lookup _search_phone_mobile_search previously searched only raw number fields returned by _phone_get_number_fields (e.g. mobile, phone). E164-normalized phone_sanitized was ignored, so searching by a sanitized value could miss records that had no match on the raw fields. This commit: - Extracts _phone_get_searchable_fields() so that both init() and _search_phone_mobile_search build the same searchable field list, appending phone_sanitized alongside mobile/phone when available. - Adds expression indexes for phone_sanitized in init() so the REGEXP_REPLACE-based queries hit indexes instead of scanning tables. - Guards init() with self._auto to prevent index creation on AbstractModel subclasses that lack a physical table. Task-6395518 ENTPR: odoo/enterprise#124797 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278018
Context: There was an enterprise field `predict_bill_product` allowing users to toggle product prediction based on line label. Before this commit, product prediction by name was running without taking into account the value of this field, which could confuse users who had disabled the feature in settings. This commit makes product prediction by name depend on this field. For community users, the prediction will run by default. no-task --- I confirm I have signed the CLA and read
Original PR description
Context: There was an enterprise field `predict_bill_product` allowing users to toggle product prediction based on line label. Before this commit, product prediction by name was running without taking into account the value of this field, which could confuse users who had disabled the feature in settings. This commit makes product prediction by name depend on this field. For community users, the prediction will run by default. no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276041 Forward-Port-Of: odoo/odoo#267138
Resolved issues and error corrections
TikTok Shop orders that arrive without a payment timestamp, such as Cash On Delivery orders, can now still be created and synchronized. The system uses the order creation time until payment confirmation is later received, preventing affected orders from being blocked.
Original PR description
**Issue**
- TikTok Shop orders may be received without any `paid_time` value in the returned API data, particularly for _Cash On Delivery ([COD](https://seller-ph.tiktok.com/university/essay?knowledge_id=10004482&lang=en)) payments.
- When creating the order, `_create_order_from_data` accessed `order_data[‘paid_time’]` directly, which triggered a `KeyError` and prevented all orders from being fully synchronised.
**Changes**
- When creating an order, if `paid_time` is missing from the data provided by TikTok:
-> `date_order` is initialised with `create_time` as a fallback
-> The new field `tiktok_payment_pending` is set to `True` to mark the order as awaiting payment confirmation.
- During subsequent synchronisations, if `paid_time` is now provided by TikTok for a pending order,
-> `date_order` is updated with the new provided timestamp and the `tiktok_payment_pending` flag is reset.
opw-6440127
Forward-Port-Of: odoo/enterprise#126797The Timesheets Assistant now ignores the current user's own email address when matching Gmail messages to customers. This prevents unrelated tasks where the user is listed as the customer from being suggested for emails they simply received.
Original PR description
Before this commit, the Timesheets Assistant resolved every address found in a read or composed email to a partner, then matched the event to a task or project having that partner as its customer. The current user is a recipient of every email they receive, so their own address is present in the "To" or "Cc" fields of every `reading_email` event. As a result, any task whose customer was the current user could be suggested for those emails. This commit excludes the current user's partner from that lookup. task-6438374
Fixed an issue where completing a field service task could get stuck and run out of memory after a delivery was returned and then re-delivered. The system now avoids repeatedly processing the same stock movements, improving reliability for teams handling product returns linked to field service work.
Original PR description
## **Steps to reproduce:** 1. Create a Service product with Create on Order set to Task and Project set to Field service project. 2. Create a Sales Order containing a storable product and a service…
## **Steps to reproduce:** 1. Create a Service product with Create on Order set to Task and Project set to Field service project. 2. Create a Sales Order containing a storable product and a service product. 3. Confirm the Sales Order to generate the project, task, and delivery order. 4. Validate the delivery order. 5. Create and validate a return for the delivery. 6. Create a return of the return to deliver the products again, but do not validate this new delivery. 7. Open the related task and click on Mark as Done button. ## **Issue:** In a delivery -> return -> return of return workflow, the stock move goes into this code https://github.com/odoo/enterprise/blob/59b86f106862c3a364ba633a1580d9051f2fe7ca/industry_fsm_stock/models/project_task.py#L89-L90 the traversal repeatedly revisits the same stock moves through move_dest_ids, causing the loop to alternate between the same move recordsets indefinitely. As a result, the loop never terminates, eventually exhausting the memory and raising a `MemoryError`. ## **Solution:** Track the stock moves that have already been visited and continue the traversal only with unseen destination moves. Runbot Video : [Video](https://drive.google.com/file/d/1wiqggjx8T-Mtl4T1JgCsfwBbgQU18nYF/view?usp=drive_link) OPW - 6420961 Forward-Port-Of: odoo/enterprise#125962
Tax return deadline dates in account report emails are now displayed using the recipient's locale settings. This prevents confusion for users in regions with different date formats and makes deadline information easier to understand.
Original PR description
The date was not formatted according to the user's locale. Forward-Port-Of: odoo/enterprise#127317
The timesheet assistant now keeps a project manually chosen by the user when switching between suggestions. This prevents accidental replacement of the selected project and helps users avoid entering timesheets under the wrong project.
Original PR description
Steps to reproduce: - Select an unmatched suggestion. - Select Project A on the timesheet form (do not save it yet). - Select another suggestion matched to Project B. Observed behavior: Project A is overridden by Project B. Expected behavior: Project A remains selected on the timesheet. By initializing `project_id` with the current record's data, we prevent the suggestion loop from overwriting the user's manual selection. task-6410844
Project tasks created from templates now skip archived users when assigning people through project roles. This prevents inactive team members from being added to new customer project work, keeping task ownership aligned with current staffing.
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users `(role.user_ids)` within the core task-copying logic in both `project` and `project_enterprise` modules. This ensures archived users are universally excluded from task assignments during template copying, regardless of what triggers the template instantiation.
Related Community PR: https://github.com/odoo/odoo/pull/274426
opw-6350841Helpdesk tickets no longer show an SLA as reached immediately after it is applied. The status now updates only when the ticket actually reaches the SLA target stage, making SLA reporting more accurate for on-time and late tickets.
Original PR description
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of…
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of the issue/feature this PR addresses: **Issue:** The `_compute_sla_reached` method in on `helpdesk_ticket.py` determines whether an SLA has been reached by checking if `exceeded_hours` is less than 0 on its `helpdesk.sla.status` records. Since every newly assigned SLA has a future deadline, `exceeded_hours` starts as negative (AKA <0), so the ticket is immediately flagged as `sla_reached = True` before any progress has been made. Conversely, a ticket that reaches its target stage after the deadline has `exceeded_hours >= 0`, so it's incorrectly flagged as `sla_reached = False` even though the SLA target was genuinely reached (it was just late). **Solution:** Change the domain in `_compute_sla_reached` to check `reached_datetime != False` instead of `exceeded_hours < 0`, matching the field already listed in the method's `@api.depends` and the same field `_sla_reach()` sets when a ticket enters its target stage. This makes `sla_reached` reflect actual stage progression rather than a time-remaining calculation. ### Current behavior before PR: A newly created ticket with a pending SLA shows `sla_reached = True` and `sla_success = True` immediately upon creation, before the ticket has moved to any target stage. SImilarly, a ticket that reaches its target stage after the SLA deadline is incorrectly marked `sla_reached = False`. ### Desired behavior after PR: `sla_reached` is False on ticket creation and only becomes True once the ticket actually enters the SLA's target stage. Lateness continues to be tracked separately and correctly via `sla_reached_late` opw-6361851 Forward-Port-Of: odoo/enterprise#126432
VoIP contact searches now recognize phone numbers even when country codes or formatting differ. This helps users find and call the right contact from the keypad or contacts tab more reliably.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6290760 compr https://github.com/odoo/odoo/pull/278018 Forward-Port-Of: odoo/enterprise#124797
Attachments added to employee records and leave requests now create documents in the expected HR folders instead of the general Employees root folder. Sick leave attachments also reliably generate related documents, making employee document management more complete and easier to navigate.
Original PR description
Before this commit, when adding an attachment to a leave or a employee version the mixin was configured to create the document in the root folder of Employees which was not very convenient. In addition, when creating a Sick leave with an attachment, no document was ever created. This commit fix both those bugs. Task-6095811 Forward-Port-Of: odoo/enterprise#120539 Forward-Port-Of: odoo/enterprise#112993
This fixes an issue where companies other than the first one could be blocked from creating quality-related operation steps when only the basic quality features were installed. The change ensures quality team email aliases have the right company context, preventing an error users could not resolve from the available screens.
Original PR description
This commit actually reverts [1] and manually forwards [2]. Suppose `mrp_workorder` installed and `quality_control` uninstalled. Because of the default value provided by [1], the only existing quality team is linked to the first company. As a result, when using another company, if the user tries to create an operation step (i.e., a QCP), it will raise an error when the onchange tries to load the default team in charge: https://github.com/odoo/enterprise/blob/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e/quality/models/quality.py#L141-L142 However, the `quality` module doesn't provide any view to create such a team. tldr The module raises an error that is actually impossible to solve... Let's avoid it in the above situation. [1] https://github.com/odoo/enterprise/commit/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e [2] https://github.com/odoo/enterprise/commit/8cd5c9322bef7db49a90d4aef844dd0ba267058e Forward-Port-Of: odoo/enterprise#126439 Forward-Port-Of: odoo/enterprise#126364
This fix helps Kenyan point-of-sale receipts display the expected SCU tax information and QR code when a valid tax signature is available. It reduces the chance of customers receiving receipts missing required electronic tax verification details after a successful order.
Original PR description
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the…
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the l10n_ke module in 'production' mode * Make an order in POS and validate it > Observation: The receipt doesn't contain the SCU information and QR Why the fix: ------------ Based on the receipt screenshot shared on the ticket (from Odoo 19.3) we can see that some informations are shown on the ticket. The information shown are the one received from the etims api, it means the call went through and the response was received. As the qrCode URL only needs `l10n_ke_oscu_signature` to be generated, we can assume that if this field is set we can safely generate the URL and generate the QR code. https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/models/pos_order.py#L252-L256 Based on this assumption we can change the condition to return the URL or not based on the presence of `l10n_ke_oscu_signature` instead of the state of the order being `sent`. In 19.0, the receipt is showing no info at all (when 19.3 is showing some info like the signature). This is also happening because the URL was falsy. And when that is the case we do not show any SCU information https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/static/src/overrides/components/order_receipt/order_receipt.xml#L56 opw-6352120 Forward-Port-Of: odoo/enterprise#127045
This fix ensures India-specific payroll calculations are only applied to Indian employee records. It prevents irrelevant Indian payroll fields from being tracked or shown when a company is using another localization, such as Belgium, reducing confusion for payroll users.
Original PR description
[FIX] l10n_in: fix some l10n_in fields computed for other localizations
Bug reproduction:
1 - in localhost install below modules:
→ l10n_in_hr_payroll,l10n_be_hr_payroll,l10n_be_hr_contract_salary
2 - Select BE, IN localizations, but as active one select Belgium. 3 - Go to employee, Laura.
4 - Change her wage to 8000
5 - In the chatter, you will see some indian fields are tracked.
→ Shouldn't be, Laura is Belgium, only BE fields should be tracked
Bug cause:
1 - In the hr.version of l10n_in_hr_payroll:
→ there isn't enough caution in compute methods for other l18ns.
→ e.g., _l10n_in_get_montly_wage returns self.wage
→ self.wage is 8000 and that function leads to positive computations
Bug solution:
1 - Non-indian versions are carefully handled in compute methods
task-6411960
Forward-Port-Of: odoo/enterprise#125350DHL Express shipments with multiple packages through EasyPost no longer fail validation because of an informational carrier message. This lets businesses complete valid international deliveries while still blocking genuine shipping errors.
Original PR description
Steps to reproduce --- 1. Configure a `delivery_easypost` shipping method using the DHL Express carrier. 2. On an international delivery, use Put in Pack to create two or more packages. 3. Validate…
Steps to reproduce --- 1. Configure a `delivery_easypost` shipping method using the DHL Express carrier. 2. On an international delivery, use Put in Pack to create two or more packages. 3. Validate the delivery. Issue --- Validation is blocked with `DHLExpress: rate_error -- DHLExpress multi-shipment rate includes this shipment.` For an EasyPost multi-shipment order, DHL Express returns the aggregate rate on the first (master) shipment only and adds an informational `rate_error` on the order stating that this rate already covers the whole order, so the remaining shipments carry no rate of their own. The message is not a real error, but `send_shipping` raises on any carrier message whose type is not exempt: https://github.com/odoo/enterprise/blob/534b42def8ae5dc884da4398377f828c49557d6e/delivery_easypost/models/easypost_request.py#L359-L364 `_post_process_ship_response` already detects and clears exactly this harmless message, but only for a hardcoded carrier allowlist introduced in a2de5bc5a14 (`Purolator`, `DPD UK`, `UPS`) that was never extended to DHL Express, so for DHL Express the message survives, reaches the raise, and aborts an otherwise valid shipment: https://github.com/odoo/enterprise/blob/a2de5bc5a14f99b8674c3ee234e4d221b406da0f/delivery_easypost/models/easypost_request.py#L416-L434 `DHL Express` is added to that allowlist so the harmless multi-shipment `rate_error` is posted on the picking and cleared instead of raised. The guard still requires a single `rate_error` carrying the "multi-shipment rate includes this shipment." text with the rate present only on the master shipment, so genuine DHL Express errors keep blocking validation. opw-6450365 Forward-Port-Of: odoo/enterprise#127164
Flexible-schedule employees who take a few hours off will no longer have the entire day treated as time off. This keeps attendance and overtime calculations accurate and shows only the actual leave period in the Time Off Gantt view.
Original PR description
Problem: On a flexible working schedule, a time off of a few hours (neither a full nor a half day) was treated as a full day off. The Attendance list then reported the whole day's attendance as…
Problem: On a flexible working schedule, a time off of a few hours (neither a full nor a half day) was treated as a full day off. The Attendance list then reported the whole day's attendance as overtime, and the Time Off gantt grayed out the entire day instead of only the leave's hours. Steps to reproduce: 1. Give an employee a flexible working schedule (e.g. 8h/day) with an overtime ruleset based on the contract's expected hours. 2. Record a 2-hour time off, then an 8-hour attendance on the same day. 3. Observe the attendance reports 8 hours of overtime instead of 2. Current behavior: A partial time off makes the whole day count as extra hours. Expected behavior: Only the hours actually taken off reduce the day's expected hours. Cause: For a flexible schedule, _handle_flexible_leave_interval expands a leave to the whole day. The override already narrows full-day and half-day leaves, but any other number of hours fell through to that full-day expansion. The expanded interval is subtracted from the day's expected hours in _work_intervals_batch, so they drop to zero and every worked hour becomes overtime. Fix: A leave of an arbitrary number of hours should only remove the hours it actually covers, so it keeps its requested interval instead of being stretched to the whole day. opw-6291536 Forward-Port-Of: odoo/enterprise#123778
Vendor bill product prediction based on line labels now respects the setting that enables or disables it. This prevents unexpected suggestions for enterprise users who turned the feature off, while keeping the default behavior for community users.
Original PR description
Context: There was an enterprise field `predict_bill_product` allowing users to toggle product prediction based on line label. Before this commit, product prediction by name was running without taking into account the value of this field, which could confuse users who had disabled the feature in settings. This commit makes product prediction by name depend on this field. For community users, the prediction will run by default. no-task --- I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/enterprise#126529
Bank reconciliation now handles imported statement lines whose payment reference contains only spaces. This prevents an unexpected error when setting accounts on affected bank statement lines, making reconciliation more reliable for data imported outside the standard UI.
Original PR description
When reconciling bank statements with an account, the system will look for past statement lines already reconciled with that account and create a reconciliation model based on common substring in…
When reconciling bank statements with an account, the system will look for past statement lines already reconciled with that account and create a reconciliation model based on common substring in payment_ref. If this payment refs contains only spaces (eg. ' '), it will trigger an index out of range traceback. This is explained by the fact that spaces are striped then '' is considered as False in some filtering leaving the list empty. From the UI, putting ' ' is not supposed to be possible because spaces are striped before write but there is many ways to import statement lines which may lead to this hence the decision of handling this scenario to make the code more robust. Steps to reproduce: 1/ Create two statement lines with payment_ref as ' ' (you can force it using a write) 2/ Click "Set account" on first one and pick 100000 Issued Capital 3/ Do the same for the second statement line => Traceback In this commit, we do not check for common substring if there is less than two labels. opw-6379977 Forward-Port-Of: odoo/enterprise#125779
Rejection notification emails now name the person who declined to sign, instead of incorrectly naming each email recipient. This helps recipients understand who rejected the document and avoids confusion in the signing process.
Original PR description
**Description of the issue/feature this PR addresses:** When a document is rejected by a signer, the notification email sent to other involved parties incorrectly displays the recipient's name in the…
**Description of the issue/feature this PR addresses:** When a document is rejected by a signer, the notification email sent to other involved parties incorrectly displays the recipient's name in the subject line instead of the person who actually refused to sign. This occurs because the subject string was using `partner.name` (the current email recipient) instead of `refuser.name`. This commit updates the string to reference the refuser, ensuring the subject accurately identifies the individual who rejected the document. **Steps to reproduce:** - Sign > upload any PDF > add signature request for 2 different signers > Send > choose signers, e.g. Abigail Carter and Marc Demo > Send - Settings > Technical > Emails > Emails - Select one of the sent emails > Sign document > sign > Validate & Send Completed Document - Select the other email > Sign document > top-right dropdown arrow > Decline to sign > Decline - Settings > Technical > Emails > Emails - Observe that all emails sent state that the recipient of the email rejected the signing **Current behavior before PR:** - Rejection email subject states that the recipient refused to sign **Desired behavior after PR is merged:** - Rejection email subject states that the refuser refused to sign opw-6421188 Forward-Port-Of: odoo/enterprise#126412
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281095 Forward-Port-Of: odoo/odoo#280550
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/file
Original PR description
### Issue: In the tax report, lines `E5`, `F3`, `F4`, `F7`, `F8` and `F9` show 0 when using a tax with the corresponding tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The E and F formulas were not updated accordingly, causing their values to be negative instead of positive ### Fix: The formulas have been updated based on the official documentation to correctly separate Sales and Purchases lines: https://www.impots.gouv.fr/sites/default/files/formulaires/3310-ca3-sd/2026/3310-ca3-sd_5426.pdf ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: E5 and F3) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, E5 and F3 lines are empty opw-6357703 Forward-Port-Of: odoo/odoo#278635
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
When importing a UBL bill, if a price-included tax is used, we need to adjust the unit price by adding the tax amount per unit. When a discount is added to the line, the unit price doesn't reflect it, but the raw_tax_amount_currency does. As a result, we add the reduced tax amount to the original unit price. We propose to compute the raw tax amount before the discount to adjust the unit price. opw-6242701 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278659
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Original PR description
On python 3.10.12 `test_export_translatable_resources` fails. This is fixed in this commit build-944659 I only tested it on 17.0 since we do not seem to have the build error on higher versions. But the minimum python version is 3.10 until [excluding saas-19.1](https://github.com/odoo/odoo/blob/11ee42b4bf70a1008b06d13a48263e42c381aeed/odoo/release.py#L39) Forward-Port-Of: odoo/odoo#281294 Forward-Port-Of: odoo/odoo#280927
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created User as a Team Member 4. Create a Template Project as follows: * Add one task to the template project * Add the created Project role to the Task 5. Create a Service Type Product with: * Create on order: Project * Project Template: Created Template 6. Archive the Created User
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users
`(role.user_ids)` within the core task-copying logic in both `project` and
`project_enterprise` modules. This ensures archived users are universally
excluded from task assignments during template copying, regardless of what
triggers the template instantiation.
Related Enterprise PR: https://github.com/odoo/enterprise/pull/125637
opw-6350841In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it
Original PR description
In ubuntu 26.04 the time zone database contents changed. A couple of timezone names are not available anymore, causing runtime exceptions. This mapping links old with new time zone naming conventions to prevent future (test) breakdown. The mapping WET to Europe/Lisbon is imperfect, and the localizations for the fixed date inside the test did not match. There exists no better nor correct mapping for WET. The mapping to Europe/Lisbon comes from the IANA tzdb-2026c and is official, so it is kept unchanged. The fixed date inside the test is changed to a recent one that aligns the test outcome with expectations: - Offsets match for recent history and future time - Match daylight savings time (DST) observation --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280691
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model
Original PR description
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three…
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_es_edi_verifactu is installed. The module adds a VeriFactu page and three warning banners to the standard invoice form without any groups restriction, so every user able to open an invoice reads three fields (l10n_es_edi_verifactu_document_ids, l10n_es_edi_verifactu_warning, l10n_es_edi_verifactu_warning_level) pointing at l10n_es_edi_verifactu.document. That model only grants read access to account.group_account_invoice and account.group_account_readonly. Steps to reproduce: - install `l10n_es_edi_verifactu` - create a salesman user with sales rights but no accounting right (*Own Documents Only* is enough) - create an ES company and an ES customer - give the salesman access to the ES company - activate Peppol in the general settings - log in as the salesman - create a sale order in the ES company for the ES customer - confirm it - click **Create Invoice** - click **Create Draft** Current behavior before PR: An error access is raised: Failed to read field account.move.l10n_es_edi_verifactu_document_ids You are not allowed to access 'Veri*Factu Document' (l10n_es_edi_verifactu.document) records. This operation is allowed for the following groups: - Invoicing/Billing - Technical/Show Accounting Features - Readonly Contact your administrator to request access if necessary. In Odoo sh (for databases 19.0), the standard test sale_management / TestSaleFlowTourPostInstall.test_basic_sale_flow_with_minimal_access_rights fails for the same reason as soon as l10n_es_edi_verifactu is installed alongside sale_management. Desired behavior after PR is merged: On a database with l10n_es_edi_verifactu installed, a non-accountant user having the possibility to create invoices should not have the error message displayed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280879
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
Original PR description
Before this commit, when the project user tries to create a task with a sale_order_id computed, he cannot because the user cannot read the comodel. This commit changes the condition to not block project user to create task if they can. The sale_order_id is actually filled by the compute method, so there is no reason to block the user. Forward-Port-Of: odoo/odoo#281380
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order
Original PR description
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install eCommerce, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Create a website for the belgian company and enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Open the website, add any product to cart, go to checkout and make a payment using SEPA **Issue:** - Check the transaction in Stripe dashboard: the order reference is currently sent only in the `Description` field which is for internal information and is not shown to customers on their bank statements. Customers only see "MACKNET", so they cannot identify which order the payment relates to. **Expected behavior:** - Should also send the order reference to Stripe's `statement_descriptor` field, which is the field used for the customer-facing bank statement reference. - The `statement_descriptor` value must comply with Stripe's requirements: Must not contain <, >, \, ', ", or * Must contain at least one letter Maximum 22 characters **Fix:** - Pass the order reference, which should already satisfy the first two requirements based on Odoo order/invoice naming conventions opw-6424994 Forward-Port-Of: odoo/odoo#280985
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80` ActivityController uses `useModel` which passes the raw `component.props` to `model.load()`, including the limit from `ir.actions.act_window` (default 80). This value ended up in `fetchActivityData` via `params.limit || this.initialLimit`, overriding `ActivityModel.DEFAULT_LIMIT` (100). The records li
Original PR description
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80`…
Steps: - Install sale_management - Make sure you have 100 quotations with 1 activity each - Open activity view - Default pager displays `1-100/100` - Activity count display `To-do 80` ActivityController uses `useModel` which passes the raw `component.props` to `model.load()`, including the limit from `ir.actions.act_window` (default 80). This value ended up in `fetchActivityData` via `params.limit || this.initialLimit`, overriding `ActivityModel.DEFAULT_LIMIT` (100). The records list was not affected because `RelationalModel._getNextConfig` never reads `params.limit` (limit is not a `SEARCH_KEY`), so it always loaded 100 records correctly. But `fetchActivityData` used 80, causing a mismatch between the records shown and the activity counts in the column headers. ```js export const SEARCH_KEYS = ["comparison", "context", "domain", "groupBy", "orderBy"]; ``` The fix strips `params.limit` in `ActivityModel.load()` before passing params to `fetchActivityData`, so it falls back to `this.initialLimit (100)`. The pager `onUpdate` handler calls `fetchActivityData` directly with its own `params.limit` and is not affected. However, `ActivityController` never forwards `limit` to the model. This is why we always have `ActivityModel.DEFAULT_LIMIT (100)` without taking into account actions's limit. To fix this we have to add the limit via `this.props.limit`, as `ListController`. `useModelWithSampleData` already had the correct behavior by calling `model.load(getSearchParams(props))` which filters out non-search params like limit. In 19.0 useModel was updated to do the same, so the issue does not exist there. Link to 19.0 fix: https://github.com/odoo/odoo/pull/211697 opw-6281125 Forward-Port-Of: odoo/odoo#280747 Forward-Port-Of: odoo/odoo#273929
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resour
Original PR description
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe…
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L735-L749 so it will get the default value which is 10 so when calling onchange for the attendance_ids_1st_week and attendance_ids_2nd_week each attendance will be set to the odd_week_seq https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L184-L200 which will then make this condition fail https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 Second part was related to the `two_weeks_calendar` when saving, its value won't be passed to the vals_list in `web_save()` as when we read the values to be changed we ignore readonly fields and since two_weeks_calendar was used in invisible condition but isn't defined in a separate `<field>` the view create a tag for it ` <field name='two_weeks_calendar' invisible='True' readonly='True' data-used-by='invisible='flexible_hours or not two_weeks_calendar' (page,working_hours)' on_change='1'/> ` This tag would be readonly by default so when the ArchParser gets each field's info it puts `two_weeks_calendar` as a readonly field and ignore it in the creation values https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/web/static/src/views/fields/field.js#L276-L279 which then fails this condition and pass all the 2 weeks attendances in the else condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L134-L138 After fixing this another bug was found where if you saved the calendar the attendances will disappear. This was happening when we create the resource.calendar.attendance records it will call the inverse method of the attendance_ids_1st_week and attendance_ids_2nd_week where they are still not computed so it will set attendance_ids to empty https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L152-L156 so after when computing the two weeks attendance it will be empty as well and it will disappear. Last bug was if after creating this you tried to switch the calendar type it will call the same validation error mentioned earlier. As when calling _get_default_attendance_ids it will try to create attendances from the company's default working schedule which will have a conflict since the company's schedule is 2-weeks schedule and we are switching our schedule to 1-week schedule so we are gonna have attendances for 2-weeks in 1-week schedule so it will fail the same condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 ## Fix: To fix those issues we needed to set the sequence values when copying the data of the company's schedule when computing the default values. Also we need to skip the inverse method when we are still upon creating the records and to do so we are passing a context in the create method to skip the inverse. Last we need to check for the difference between the schedule type and the company's schedule when fetching the default attendances. opw-6374237 Forward-Port-Of: odoo/odoo#279182
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creatin
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#275653
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
Original PR description
The test `waitForAnimationFrame does not trigger update if interaction is not ready yet` fails randomly (and seldom). The timeout and animation frame are treated together and appear at the same time in the verified steps. This is likely due to the timeout being too close to the animation frame and the task queue resolving them back to back. Giving a larger timeout (1s instead of 100ms) should solve the issue. runbot-939992 Forward-Port-Of: odoo/odoo#280708
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/b
Original PR description
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not…
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/chatter/web/chatter_patch.js#L106-L138 Since the composer of the message in edition has no dropzone, a file dropped on it is caught by the chatter dropzone and ends up attached to the record instead of the message. Fix: Pass the message body as dropzoneRef to the composer in message.xml. The composer then creates its own dropzone over the message, the same way the chatter composer gets one from chatter.xml, and the dropped file is added to the message in edition. The chatter dropzone and the thread composer dropzone cover that same area and would show at the same time, so both are turned off while a message is in edition. The thread already knows which message that is through messageInEdition, so neither of them has anything to keep track of. Steps to reproduce: 1. Open the Contacts app and open any contact 2. Click Log note, type some text and click Log 3. Hover the note and click the pencil icon to edit it 4. Drag a file from the file explorer and drop it on the note => the file is added to the attachments of the contact instead of the note Ticket [link](https://www.odoo.com/odoo/project.task/6385377) opw-6385377 Forward-Port-Of: odoo/odoo#278373
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs: Failed to find 1 of "span" with text "This livechat conversation has ended." (Timeout of 10 seconds). Found 0 instead. This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of t
Original PR description
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs:
Failed to find 1 of "span" with text "This livechat conversation
has ended." (Timeout of 10 seconds). Found 0 instead.
This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of the visitor leaving, so the date goes back to `false` and the conversation still looks open.
One solution could have been to use `waitStoreFetch`, but its step comes from that same callback, and the helper returns six microtasks before the answer is inserted, on a hundred runs out of a hundred.
This commit fixes the issue by waiting for the messaging menu to list a plain channel, which arrives with the `channels_as_member` answer only.
https://runbot.odoo.com/odoo/error/945672