Daily updates from Odoo
Friday, July 31, 2026
330 changes
13 changes
Enhancements to existing features
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag an
Original PR description
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag and drop questions Original PR (18.0): odoo/odoo#270576 opw-6260478 Forward-Port-Of: odoo/odoo#277071
Resolved issues and error corrections
Steps: - Install portal app - Go to my/addresses page. - Update main address of current user. Issues: - `Main Address` badge is not visible on main address. - Editing main address is not opening `my/account` page. Cause: - Since PR https://github.com/odoo/odoo/pull/232539 t-call syntax changed and expect to add attribute directly instead t-set but forget to adept it for `is_user_address` and `address_update_url`. Fix: - Move those variable directly into t-call instead t-set. For
Original PR description
Steps: - Install portal app - Go to my/addresses page. - Update main address of current user. Issues: - `Main Address` badge is not visible on main address. - Editing main address is not opening `my/account` page. Cause: - Since PR https://github.com/odoo/odoo/pull/232539 t-call syntax changed and expect to add attribute directly instead t-set but forget to adept it for `is_user_address` and `address_update_url`. Fix: - Move those variable directly into t-call instead t-set. Forward-Port-Of: odoo/odoo#278812
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_tax_luxury_sales ``` Reason-1 : - In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were ad
Original PR description
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise…
Error-1 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system:
account.1_l10n_id_domestic_fiscal_position
```
Error-2 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system: account.1_tax_luxury_sales
```
Reason-1 :
- In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were added and linked to acc.tax using fiscal_position_ids .
- In [this](https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_id/migrations/1.3/end-migrate_update_taxes.py) migration script, while creating taxes it didnt find fiscal positions, so need to create them first.
Reason-2 :
- original_tax_ids was also added in same commit, if client deleted those tax(ie tax_luxury_sales) will fail while creating `tax_luxury_sales_pemungut_ppn`, It needs to be created first too.
- upg : [4341887](https://upgrade.odoo.com/odoo/upgrade.request/4341887)
- opw : [6285978](https://www.odoo.com/odoo/project/70/tasks/6285978)
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#269802Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record. - Delete its `linked overtime rules`. - Install the `hr_holidays_attendance` module. **Error:** ```py Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule' odoo.tools.conver
Original PR description
Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` >…
Currently, an error occurs when installing the hr_holidays_attendance module.
**Steps to Reproduce:**
- Install the `hr_attendance` module without demo data.
- Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record.
- Delete its `linked overtime rules`.
- Install the `hr_holidays_attendance` module.
**Error:**
```py
Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule'
odoo.tools.convert.ParseError: while parsing /home/odoo/odoo18/community/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml:7, somewhere inside <record id="hr_attendance.hr_attendance_overtime_employee_schedule_rule" model="hr.attendance.overtime.rule">
<field name="compensable_as_leave" eval="True"/>
</record>
```
This error occurs when the user deletes all overtime rules and then installs the hr_holidays_attendance
module. During installation, the module attempts to update the deleted overtime rule records,
which raises an error [1].
This commit uses forcecreate="0" to skip updating records if the corresponding overtime
rules do not exist.
[1]- https://github.com/odoo/odoo/blob/da0a83761f38ee4a2940015b6c8f7190c310a4a0/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml#L7-L12
sentry-7372074675
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279088
Forward-Port-Of: odoo/odoo#277656Reading the `display_name` of a working schedule line of a 2 weeks calendar crashes: the compute reads `record.weektype` while the field is named `week_type`. ### Steps to reproduce - Switch a working schedule to a 2 weeks calendar. - Open one of its lines in a form view, e.g. with the `View Button` optional column in developer mode. opw-6427314 Forward-Port-Of: odoo/odoo#279194
Original PR description
Reading the `display_name` of a working schedule line of a 2 weeks calendar crashes: the compute reads `record.weektype` while the field is named `week_type`. ### Steps to reproduce - Switch a working schedule to a 2 weeks calendar. - Open one of its lines in a form view, e.g. with the `View Button` optional column in developer mode. opw-6427314 Forward-Port-Of: odoo/odoo#279194
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`. Deleting such a cash move then crashes in `delete_cash_in_out`: File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out action = cashier_name +
Original PR description
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner…
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`.
Deleting such a cash move then crashes in `delete_cash_in_out`:
File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out
action = cashier_name + ': ' + str(amount)
TypeError: unsupported operand type(s) for +: 'bool' and 'str'
Steps to reproduce:
- Enable "Multi Employees per Session" (pos_hr) on a PoS config
- Archive the work contact of an employee, or make sure it is not included in the limited partner loading
- Open a session, log in as that employee and register a cash in/out
- As a manager, delete the cash move from the cash move list => Traceback, the cash move cannot be deleted
opw-6389830
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278462
Forward-Port-Of: odoo/odoo#276598[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tri
Original PR description
[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tries to create a new Ir.Sequence (ex: editing a custom Lot/Serial) it will still throw him an error as he is not Role/Administrator Fix: To avoid the permissions issue at the time of creation we use sudo to bypass the Role/User lack of permissions. opw-6269415 Forward-Port-Of: odoo/odoo#278453 Forward-Port-Of: odoo/odoo#268799
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired Connection
Original PR description
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired ConnectionToken. Move reader discovery to `connectReader()` so Odoo connects using fresh discovery results, and stop discovering readers eagerly when creating the Stripe Terminal instance. opw-6311626 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277765 Forward-Port-Of: odoo/odoo#276875
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387 Forward-Port-Of: odoo/odoo#279184 Forward-Port-Of: odoo/odoo#274398
Following the rework of payment provider states (cf. PR https://github.com/odoo/odoo/pull/249545), `_toggle_post_processing_cron` only checked for installed providers using `module_state in ('installed', 'to install')`. However, providers that are not linked to a specific module (such as custom providers or test providers) have `module_id = False`, which causes `module_state` to evaluate to `False`. As a result, setting up these providers left the post-processing cron inactive, causing `test
Original PR description
Following the rework of payment provider states (cf. PR https://github.com/odoo/odoo/pull/249545),
`_toggle_post_processing_cron` only checked for installed providers using `module_state in ('installed', 'to install')`.
However, providers that are not linked to a specific module (such as custom providers or test providers) have `module_id = False`, which causes `module_state` to evaluate to `False`. As a result, setting up these providers left the post-processing cron inactive, causing `test_installing_provider_activates_post_processing_cron` to fail.
This commit updates the search domain in
`_toggle_post_processing_cron()` to also include providers where `module_id = False`, matching the domain logic used in `_find_available_providers()`.
runbot-940173Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#26751
Original PR description
Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#267510
The mail.message/delete bus handler accessed selfMember?.seen_message_id.id with optional chaining only on selfMember, not on seen_message_id. When a member has never seen any message in a channel (seen_message_id is False), accessing .id threw 'TypeError: can't access property id, selfMember.seen_message_id is undefined', breaking message deletion for that user (e.g. deleting a message in a channel the user never opened. Add optional chaining on seen_message_id so the unread counter is simpl
Original PR description
The mail.message/delete bus handler accessed selfMember?.seen_message_id.id with optional chaining only on selfMember, not on seen_message_id. When a member has never seen any message in a channel (seen_message_id is False), accessing .id threw 'TypeError: can't access property id, selfMember.seen_message_id is undefined', breaking message deletion for that user (e.g. deleting a message in a channel the user never opened. Add optional chaining on seen_message_id so the unread counter is simply not decremented when no message has been seen yet. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279279 Forward-Port-Of: odoo/odoo#277417
Documentation and clarification updates
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representat
Original PR description
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representative of bobco GmbH. The signatory line has been finalized as: `Philip Braun philip@braun.tf https://github.com/philipbr` --- The corporate CLA has been signed by Philip Braun, and the PR guidelines at www.odoo.com/submit-pr have been read. Forward-Port-Of: odoo/odoo#279348
14 changes
Enhancements to existing features
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag an
Original PR description
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag and drop questions Original PR (18.0): odoo/odoo#270576 opw-6260478 Forward-Port-Of: odoo/odoo#277071
Resolved issues and error corrections
Steps: - Install portal app - Go to my/addresses page. - Update main address of current user. Issues: - `Main Address` badge is not visible on main address. - Editing main address is not opening `my/account` page. Cause: - Since PR https://github.com/odoo/odoo/pull/232539 t-call syntax changed and expect to add attribute directly instead t-set but forget to adept it for `is_user_address` and `address_update_url`. Fix: - Move those variable directly into t-call instead t-set. For
Original PR description
Steps: - Install portal app - Go to my/addresses page. - Update main address of current user. Issues: - `Main Address` badge is not visible on main address. - Editing main address is not opening `my/account` page. Cause: - Since PR https://github.com/odoo/odoo/pull/232539 t-call syntax changed and expect to add attribute directly instead t-set but forget to adept it for `is_user_address` and `address_update_url`. Fix: - Move those variable directly into t-call instead t-set. Forward-Port-Of: odoo/odoo#278812
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_tax_luxury_sales ``` Reason-1 : - In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were ad
Original PR description
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise…
Error-1 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system:
account.1_l10n_id_domestic_fiscal_position
```
Error-2 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system: account.1_tax_luxury_sales
```
Reason-1 :
- In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were added and linked to acc.tax using fiscal_position_ids .
- In [this](https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_id/migrations/1.3/end-migrate_update_taxes.py) migration script, while creating taxes it didnt find fiscal positions, so need to create them first.
Reason-2 :
- original_tax_ids was also added in same commit, if client deleted those tax(ie tax_luxury_sales) will fail while creating `tax_luxury_sales_pemungut_ppn`, It needs to be created first too.
- upg : [4341887](https://upgrade.odoo.com/odoo/upgrade.request/4341887)
- opw : [6285978](https://www.odoo.com/odoo/project/70/tasks/6285978)
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#269802Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record. - Delete its `linked overtime rules`. - Install the `hr_holidays_attendance` module. **Error:** ```py Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule' odoo.tools.conver
Original PR description
Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` >…
Currently, an error occurs when installing the hr_holidays_attendance module.
**Steps to Reproduce:**
- Install the `hr_attendance` module without demo data.
- Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record.
- Delete its `linked overtime rules`.
- Install the `hr_holidays_attendance` module.
**Error:**
```py
Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule'
odoo.tools.convert.ParseError: while parsing /home/odoo/odoo18/community/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml:7, somewhere inside <record id="hr_attendance.hr_attendance_overtime_employee_schedule_rule" model="hr.attendance.overtime.rule">
<field name="compensable_as_leave" eval="True"/>
</record>
```
This error occurs when the user deletes all overtime rules and then installs the hr_holidays_attendance
module. During installation, the module attempts to update the deleted overtime rule records,
which raises an error [1].
This commit uses forcecreate="0" to skip updating records if the corresponding overtime
rules do not exist.
[1]- https://github.com/odoo/odoo/blob/da0a83761f38ee4a2940015b6c8f7190c310a4a0/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml#L7-L12
sentry-7372074675
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279088
Forward-Port-Of: odoo/odoo#277656### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387 Forward-Port-Of: odoo/odoo#279184 Forward-Port-Of: odoo/odoo#274398
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`. Deleting such a cash move then crashes in `delete_cash_in_out`: File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out action = cashier_name +
Original PR description
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner…
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`.
Deleting such a cash move then crashes in `delete_cash_in_out`:
File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out
action = cashier_name + ': ' + str(amount)
TypeError: unsupported operand type(s) for +: 'bool' and 'str'
Steps to reproduce:
- Enable "Multi Employees per Session" (pos_hr) on a PoS config
- Archive the work contact of an employee, or make sure it is not included in the limited partner loading
- Open a session, log in as that employee and register a cash in/out
- As a manager, delete the cash move from the cash move list => Traceback, the cash move cannot be deleted
opw-6389830
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278462
Forward-Port-Of: odoo/odoo#276598`onClickValidate`'s signature changed to `onClickValidate(args = {})`, so passing `true` directly from the Viva app callback made `isForceValidate` silently resolve to `false` instead of `true`. The previous `validateOrder` override was also dead code, since that method moved off `PaymentScreen` to `PosStore` and so we now override `onClickValidate` instead.
Original PR description
`onClickValidate`'s signature changed to `onClickValidate(args = {})`, so passing `true` directly from the Viva app callback made `isForceValidate` silently resolve to `false` instead of `true`.
The previous `validateOrder` override was also dead code, since that method moved off `PaymentScreen` to `PosStore` and so we now override `onClickValidate` instead.[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tri
Original PR description
[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tries to create a new Ir.Sequence (ex: editing a custom Lot/Serial) it will still throw him an error as he is not Role/Administrator Fix: To avoid the permissions issue at the time of creation we use sudo to bypass the Role/User lack of permissions. opw-6269415 Forward-Port-Of: odoo/odoo#278453 Forward-Port-Of: odoo/odoo#268799
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired Connection
Original PR description
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired ConnectionToken. Move reader discovery to `connectReader()` so Odoo connects using fresh discovery results, and stop discovering readers eagerly when creating the Stripe Terminal instance. opw-6311626 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277765 Forward-Port-Of: odoo/odoo#276875
Reading the `display_name` of a working schedule line of a 2 weeks calendar crashes: the compute reads `record.weektype` while the field is named `week_type`. ### Steps to reproduce - Switch a working schedule to a 2 weeks calendar. - Open one of its lines in a form view, e.g. with the `View Button` optional column in developer mode. opw-6427314 Forward-Port-Of: odoo/odoo#279194
Original PR description
Reading the `display_name` of a working schedule line of a 2 weeks calendar crashes: the compute reads `record.weektype` while the field is named `week_type`. ### Steps to reproduce - Switch a working schedule to a 2 weeks calendar. - Open one of its lines in a form view, e.g. with the `View Button` optional column in developer mode. opw-6427314 Forward-Port-Of: odoo/odoo#279194
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only
Original PR description
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's…
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only one of them: - `off` is ignored when the input has a name and Chrome holds autofill (address) data for it. - `new-password` is ignored when Chrome offers "frequently used values", i.e. the form-history dropdown. [3] So `new-password` does not always work. It only stays hidden while the field is ineligible for those suggestions. A field becomes eligible as soon as it gains an `id` and an associated `<label>`. On `saas-19.3` this is provable on commit [4] where adding a prefix icon gave the link popover URL input an `id` + `<label for>`, and the native dropdown resurfaced over the custom URL/page suggestions. This branch targets `saas-18.4`, where the regression is NOT reproducible because that URL input has no `id`/`label` yet. The fix is applied here anyway to avoid the gap that any later `label`/`id` addition re-exposes (as commit [4] proved), and the fix can be forward ported to `saas-19.3`. The website editor's URL field implements autocomplete without the `AutoComplete` component, so the default does not reach it. so `autocomplete="off"` is set directly on that input. [1]: https://github.com/odoo/odoo/commit/9c0f5612 [2]: https://github.com/odoo/odoo/commit/2980694b (opw-4551051) [3]: https://issues.chromium.org/issues/41163264#comment30 [4]: https://github.com/odoo/odoo/commit/2b4d04d1 (task-6034288) task-6370552 Forward-Port-Of: odoo/odoo#279203 Forward-Port-Of: odoo/odoo#277501
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back
Original PR description
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is…
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back to the planned "days to receive" when nothing has been received yet according to [task](https://www.odoo.com/odoo/project/809/tasks/3691573). The query instead computes age(date_planned, COALESCE(date_done, date_order)), so once a receipt exists it returns date_planned - date_done (the gap between the scheduled date and the receipt) rather than date_done - date_order. https://github.com/odoo/odoo/blob/c06be48ce7277a667719fd756e0a1f63e91cda27/addons/purchase_stock/report/purchase_report.py#L20-L28 opw-6226523 Forward-Port-Of: odoo/odoo#279267 Forward-Port-Of: odoo/odoo#268843
Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#26751
Original PR description
Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#267510
Documentation and clarification updates
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representat
Original PR description
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representative of bobco GmbH. The signatory line has been finalized as: `Philip Braun philip@braun.tf https://github.com/philipbr` --- The corporate CLA has been signed by Philip Braun, and the PR guidelines at www.odoo.com/submit-pr have been read. Forward-Port-Of: odoo/odoo#279348
16 changes
Enhancements to existing features
If a list item has a selection blocker, the user can be stuck and forced to move to the previous or next block instead of being able to continue to edit the list item. To get around this, this commit allows selection placeholders in list items. task-6394918 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278323
Original PR description
If a list item has a selection blocker, the user can be stuck and forced to move to the previous or next block instead of being able to continue to edit the list item. To get around this, this commit allows selection placeholders in list items. task-6394918 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278323
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag an
Original PR description
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag and drop questions Original PR (18.0): odoo/odoo#270576 opw-6260478 Forward-Port-Of: odoo/odoo#277071
Resolved issues and error corrections
# How to reproduce - Go to a website page - Add atleast one image to the page - Go to Site > Optimize SEO - Add a description to an image - Save # The issue The description is not applied to the image. It is not present in the image's alt in the page and if we re-open the SEO modal, it is not there either. # Cause This [PR] changed the way the image's id are generated in `get_alt_image()`, but did not change the id generation in the check done in `update_alt_images()`, so this check
Original PR description
# How to reproduce - Go to a website page - Add atleast one image to the page - Go to Site > Optimize SEO - Add a description to an image - Save # The issue The description is not applied to the image. It is not present in the image's alt in the page and if we re-open the SEO modal, it is not there either. # Cause This [PR] changed the way the image's id are generated in `get_alt_image()`, but did not change the id generation in the check done in `update_alt_images()`, so this check always fails: https://github.com/odoo/odoo/blob/36eee85dbaed927ff76b2d44a44ba476e9588c72/addons/website/controllers/main.py#L894 [PR]: https://github.com/odoo/odoo/commit/1f1980a1d9835567597ca239d404f47d4677dc47 # Proposed solution Added an helper function for the id generation. This is not necessary but might prevent this from happening again, up to the reviewer to keep it or not opw-6389523 Forward-Port-Of: odoo/odoo#278675 Forward-Port-Of: odoo/odoo#277588
While preloading chart template data, if an account already exists in the db but has `active=False`, it is not found because archived records are excluded from the [`_search`]. As a result, the load attempts to create a new account. During creation, the Python constraint [`_ensure_code_is_unique`] searches with `active_test=False`, finds the archived account with the same code, and raises a ValidationError: ```py File "/home/odoo/src/odoo/saas-19.2/addons/account/models/chart_template.py"
Original PR description
While preloading chart template data, if an account already exists in the db but has `active=False`, it is not found because archived records are excluded from the [`_search`]. As a result, the load…
While preloading chart template data, if an account already exists in the db but has `active=False`, it is not found because archived records are excluded from the [`_search`].
As a result, the load attempts to create a new account. During creation, the Python constraint [`_ensure_code_is_unique`] searches with `active_test=False`, finds the archived account with the same code, and raises a ValidationError:
```py
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/chart_template.py", line 735, in _load_data
'noupdate': True,
^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 4519, in _load_records
records = self._load_records_create([data['values'] for data in to_create])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 4426, in _load_records_create
records = self.create(vals_list)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/decorators.py", line 363, in create
return method(self, vals_list)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_account.py", line 1057, in create
records._ensure_code_is_unique()
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_account.py", line 1135, in _ensure_code_is_unique
raise ValidationError(
odoo.exceptions.ValidationError: Account codes must be unique. You can't create accounts with these duplicate codes: 1.1.1.02.003, 1.1.1.02.004
```
Steps to reproduce:
- In a `v19.0` database, install `l10n_ar` with demo data.
- The accounts with codes `1.1.1.02.003` and `1.1.1.02.004` are created by [`_create_outstanding_accounts`].
- Archive those accounts and upgrade to `v19.2`.
- During the upgrade, [`_get_latam_check_outstanding_account_account`] attempts to create new accounts with the same codes, triggering the duplicate code validation.
tbg-2840
[`_search`]: https://github.com/odoo/odoo/blob/619d8ce9f31349ed06b11ead4988a4a1d9ca6bdd/addons/account/models/chart_template.py#L438
[`_ensure_code_is_unique`]: https://github.com/odoo/odoo/blob/19.0/addons/account/models/account_account.py#L1133
[`_create_outstanding_accounts`]: https://github.com/odoo/odoo/blob/06a46b083fde5688d71c5602553316c9e7160b6a/addons/account/models/chart_template.py#L925C9-L949
[`_get_latam_check_outstanding_account_account`]: https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_latam_check/models/account_chart_template.py#L60-L76
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279313
Forward-Port-Of: odoo/odoo#279092**Problem:** When creating a new task, the Customer does not follow the project the user selects: once a first project has filled it, selecting another project keeps the previous project's customer. **Steps to reproduce:** 1. Create a new task and select a project that has a customer. 2. The Customer is set to that project's customer. 3. Select another project configured with a different customer. 4. Observe the Customer keeps the first project's customer. **Current behavior:** The C
Original PR description
**Problem:** When creating a new task, the Customer does not follow the project the user selects: once a first project has filled it, selecting another project keeps the previous project's customer.…
**Problem:** When creating a new task, the Customer does not follow the project the user selects: once a first project has filled it, selecting another project keeps the previous project's customer. **Steps to reproduce:** 1. Create a new task and select a project that has a customer. 2. The Customer is set to that project's customer. 3. Select another project configured with a different customer. 4. Observe the Customer keeps the first project's customer. **Current behavior:** The Customer keeps the first selected project's customer. **Expected behavior:** The Customer follows the selected project and shows its customer. **Cause of the issue:** partner_id is filled by _compute_partner_id, which only assigns a partner while the field is empty. Once a project has filled it, selecting another project no longer refreshes the now non-empty Customer. **Fix:** Refresh the Customer from the project on project_id change, but only while the task is new (no _origin). An existing task's customer is left untouched, since it may already carry sale order lines, timesheets, materials or worksheets that must not be reset when the project changes. opw-6315902 Forward-Port-Of: odoo/odoo#278526 Forward-Port-Of: odoo/odoo#276211
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5 karma (to give him enough rights to answer and comment) - Connect with the portal user and go to the post - Create an answer - Try to comment on your own answer - AccessError is raised **Issue:** Since [1] we check comodel access (in this case `res.partner`) when adding records. Here
Original PR description
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5…
**Steps to reproduce:**
- Install website_forum
- Create a new post on the forum with the admin
- Subscribe to the post notifications using the bell button
- Create a new portal user and give him 5 karma
(to give him enough rights to answer and comment)
- Connect with the portal user and go to the post
- Create an answer
- Try to comment on your own answer
- AccessError is raised
**Issue:**
Since [1] we check comodel access (in this case `res.partner`) when adding records. Here during the `message_post` the `question_followers` are added manually as `partner_ids` before sending (the logic only relies on the original post subscribers, not on the added comment/reply).
```py
question_followers = self.env['mail.followers'].sudo().search([
('res_model', '=', self._name),
('res_id', '=', self.parent_id.id),
('partner_id', '!=', False),
]).filtered(lambda fol: comment_subtype in fol.subtype_ids).mapped('partner_id')
partner_ids += question_followers.ids
```
As the portal user has no `read` access to the subscribers the message creation fails with a traceback.
**Fix:**
Add `sudo` to the `message_post` call of `post_comment`.
[1] https://github.com/odoo/odoo/commit/aae732957c3c3b3590f5686cfccc0ab264d0b5c9
opw-5318757
Forward-Port-Of: odoo/odoo#278840
Forward-Port-Of: odoo/odoo#274751When displaying lots or serial numbers on invoices, the quantity and UoM were rendered without any separator in the SN/LN table, e.g. `1.00Units`. - Add a non-breaking space between the quantity and UoM so the table renders as `1.00 Units`. - Also align the SN/LN value cell consistently with its right-aligned column header. - Update the `sale_stock` and `sale_mrp` report tests to expect whitespace between the quantity and UoM in the rendered invoice output. Task [link](https://www.odoo.
Original PR description
When displaying lots or serial numbers on invoices, the quantity and UoM were rendered without any separator in the SN/LN table, e.g. `1.00Units`. - Add a non-breaking space between the quantity and UoM so the table renders as `1.00 Units`. - Also align the SN/LN value cell consistently with its right-aligned column header. - Update the `sale_stock` and `sale_mrp` report tests to expect whitespace between the quantity and UoM in the rendered invoice output. Task [link](https://www.odoo.com/odoo/project/967/tasks/6365178) task-6365178 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279214 Forward-Port-Of: odoo/odoo#274660
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387 Forward-Port-Of: odoo/odoo#279184 Forward-Port-Of: odoo/odoo#274398
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`. Deleting such a cash move then crashes in `delete_cash_in_out`: File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out action = cashier_name +
Original PR description
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner…
With pos_hr enabled, the cash in/out popup uses the cashier's `work_contact_id` as partner for the `account.bank.statement.line`. When that partner is archived or not part of the limited partner loading, the relation cannot be resolved in the frontend and the statement line is created with `partner_id = False`.
Deleting such a cash move then crashes in `delete_cash_in_out`:
File ".../point_of_sale/models/pos_session.py", line 1877, in delete_cash_in_out
action = cashier_name + ': ' + str(amount)
TypeError: unsupported operand type(s) for +: 'bool' and 'str'
Steps to reproduce:
- Enable "Multi Employees per Session" (pos_hr) on a PoS config
- Archive the work contact of an employee, or make sure it is not included in the limited partner loading
- Open a session, log in as that employee and register a cash in/out
- As a manager, delete the cash move from the cash move list => Traceback, the cash move cannot be deleted
opw-6389830
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278462
Forward-Port-Of: odoo/odoo#276598Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used
Original PR description
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used while preserving the existing validation against empty or whitespace-only names. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279365 Forward-Port-Of: odoo/odoo#273593
[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tri
Original PR description
[FIX] stock: fix user permission to edit lots Issue: An user with the Role/User that is Inventory/Administrator is unable to edit the custom Lot/Serial Steps to reproduce: 1. Take a user with Role/User 2. Assign them Inventory/Administrator 3. Log in as this user and create a product tracked by lots 4. Go to the Inventory tab and try editing the field Custom Lot/Serial Cause: Only Role/Administrator can create Ir.Sequence, therefore even if a Role/User is Inventory/Administrator tries to create a new Ir.Sequence (ex: editing a custom Lot/Serial) it will still throw him an error as he is not Role/Administrator Fix: To avoid the permissions issue at the time of creation we use sudo to bypass the Role/User lack of permissions. opw-6269415 Forward-Port-Of: odoo/odoo#278453 Forward-Port-Of: odoo/odoo#268799
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only
Original PR description
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's…
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only one of them: - `off` is ignored when the input has a name and Chrome holds autofill (address) data for it. - `new-password` is ignored when Chrome offers "frequently used values", i.e. the form-history dropdown. [3] So `new-password` does not always work. It only stays hidden while the field is ineligible for those suggestions. A field becomes eligible as soon as it gains an `id` and an associated `<label>`. On `saas-19.3` this is provable on commit [4] where adding a prefix icon gave the link popover URL input an `id` + `<label for>`, and the native dropdown resurfaced over the custom URL/page suggestions. This branch targets `saas-18.4`, where the regression is NOT reproducible because that URL input has no `id`/`label` yet. The fix is applied here anyway to avoid the gap that any later `label`/`id` addition re-exposes (as commit [4] proved), and the fix can be forward ported to `saas-19.3`. The website editor's URL field implements autocomplete without the `AutoComplete` component, so the default does not reach it. so `autocomplete="off"` is set directly on that input. [1]: https://github.com/odoo/odoo/commit/9c0f5612 [2]: https://github.com/odoo/odoo/commit/2980694b (opw-4551051) [3]: https://issues.chromium.org/issues/41163264#comment30 [4]: https://github.com/odoo/odoo/commit/2b4d04d1 (task-6034288) task-6370552 Forward-Port-Of: odoo/odoo#279203 Forward-Port-Of: odoo/odoo#277501
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired Connection
Original PR description
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired ConnectionToken. Move reader discovery to `connectReader()` so Odoo connects using fresh discovery results, and stop discovering readers eagerly when creating the Stripe Terminal instance. opw-6311626 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277765 Forward-Port-Of: odoo/odoo#276875
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back
Original PR description
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is…
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back to the planned "days to receive" when nothing has been received yet according to [task](https://www.odoo.com/odoo/project/809/tasks/3691573). The query instead computes age(date_planned, COALESCE(date_done, date_order)), so once a receipt exists it returns date_planned - date_done (the gap between the scheduled date and the receipt) rather than date_done - date_order. https://github.com/odoo/odoo/blob/c06be48ce7277a667719fd756e0a1f63e91cda27/addons/purchase_stock/report/purchase_report.py#L20-L28 opw-6226523 Forward-Port-Of: odoo/odoo#279267 Forward-Port-Of: odoo/odoo#268843
Documentation and clarification updates
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representat
Original PR description
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representative of bobco GmbH. The signatory line has been finalized as: `Philip Braun philip@braun.tf https://github.com/philipbr` --- The corporate CLA has been signed by Philip Braun, and the PR guidelines at www.odoo.com/submit-pr have been read. Forward-Port-Of: odoo/odoo#279348
Miscellaneous changes
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclus
Original PR description
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclusions from multiple != operators to a single not in. Explain Before: https://explain.dalibo.com/plan/84095dcgfdc158a2 Explain After: https://explain.dalibo.com/plan/ag2abcdf4ge5d5e5 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278739
6 changes
Resolved issues and error corrections
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only
Original PR description
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's…
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only one of them: - `off` is ignored when the input has a name and Chrome holds autofill (address) data for it. - `new-password` is ignored when Chrome offers "frequently used values", i.e. the form-history dropdown. [3] So `new-password` does not always work. It only stays hidden while the field is ineligible for those suggestions. A field becomes eligible as soon as it gains an `id` and an associated `<label>`. On `saas-19.3` this is provable on commit [4] where adding a prefix icon gave the link popover URL input an `id` + `<label for>`, and the native dropdown resurfaced over the custom URL/page suggestions. This branch targets `saas-18.4`, where the regression is NOT reproducible because that URL input has no `id`/`label` yet. The fix is applied here anyway to avoid the gap that any later `label`/`id` addition re-exposes (as commit [4] proved), and the fix can be forward ported to `saas-19.3`. The website editor's URL field implements autocomplete without the `AutoComplete` component, so the default does not reach it. so `autocomplete="off"` is set directly on that input. [1]: https://github.com/odoo/odoo/commit/9c0f5612 [2]: https://github.com/odoo/odoo/commit/2980694b (opw-4551051) [3]: https://issues.chromium.org/issues/41163264#comment30 [4]: https://github.com/odoo/odoo/commit/2b4d04d1 (task-6034288) task-6370552 Forward-Port-Of: odoo/odoo#279203 Forward-Port-Of: odoo/odoo#277501
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387 Forward-Port-Of: odoo/odoo#279184 Forward-Port-Of: odoo/odoo#274398
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2
Original PR description
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through…
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2 USD (= 80 ZIG) was correctly shown as 80 ZIG on its own, yet appeared as 2 ZIG once it was part of a combo, since the raw amount was displayed as-is in the PoS currency. Convert `base_price` and `extra_price` from each record's own `currency_id` to the PoS currency at load time, mirroring what is already done for product prices. Steps to reproduce: - Set a product to 2 USD and a PoS to a ZIG pricelist (rate 40). - Open the PoS: the standalone product shows 80 ZIG. - Add the same product as a combo item: it shows 2 ZIG instead of 80 ZIG. opw-6410243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278330
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating th
Original PR description
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating the product name, we should first check that it would not result in an empty description picking. opw-6318785 Forward-Port-Of: odoo/odoo#275248
Documentation and clarification updates
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representat
Original PR description
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representative of bobco GmbH. The signatory line has been finalized as: `Philip Braun philip@braun.tf https://github.com/philipbr` --- The corporate CLA has been signed by Philip Braun, and the PR guidelines at www.odoo.com/submit-pr have been read. Forward-Port-Of: odoo/odoo#279348
Miscellaneous changes
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclus
Original PR description
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclusions from multiple != operators to a single not in. Explain Before: https://explain.dalibo.com/plan/84095dcgfdc158a2 Explain After: https://explain.dalibo.com/plan/ag2abcdf4ge5d5e5 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278739
1 change
Resolved issues and error corrections
Steps to reproduce: Use the real testing credentials Create a SEZ partner Create an invoice and ewaybill Select the type of Ewaybill as Export Tax Invoice We get error code-450 which clearly states, `450 For outward-export ewaybill, To GSTIN has to be either URP or SEZ` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Steps to reproduce: Use the real testing credentials Create a SEZ partner Create an invoice and ewaybill Select the type of Ewaybill as Export Tax Invoice We get error code-450 which clearly states, `450 For outward-export ewaybill, To GSTIN has to be either URP or SEZ` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
36 changes
Enhancements to existing features
Quality managers can now find existing Quality Spreadsheet Templates in the spreadsheet selector when templates are available. This makes it easier to insert list views into quality reporting templates and reuse them without extra workarounds.
Original PR description
Before this commit: - Quality Spreadsheet Templates were not available in the spreadsheet selector. - Quality managers could not insert list views into existing Quality Spreadsheet Templates. After this commit: - Quality Spreadsheet Templates are exposed in the spreadsheet selector when at least one template exists. - The session `can_insert_in_spreadsheet` flag is enabled for Quality managers in that case. Task: [6321126](https://www.odoo.com/odoo/project/2328/tasks/6321126)
The Documents app interface has been updated to make common actions easier to find and reduce visual clutter. This improves day-to-day document management by presenting a cleaner, more focused experience for users.
Original PR description
Task-6313958
The French localization reporting screens have been updated to work with the latest interface framework used by Odoo. This keeps fiscal declaration and reporting features maintainable and aligned with platform upgrades, with little expected change for end users.
Original PR description
Update the code of l10n_fr_{pdp,reports} to follow the new Owl 3.
task-6353237
Linked:https://github.com/odoo/odoo/pull/278004Online rental bookings now use a working-time calendar instead of simple unavailable-day rules. Customers see date-only selection plus available pickup and return times, reducing booking errors caused by inconsistent rental schedules.
Original PR description
Replace the unavailability days with a resource calendar. Dates are considered valid if the start and return dates are within the working intervals. For non hourly-period products, only the date is checked, while for the hourly-period products, the exact time matters. This prevents misconfiguration issue with a calendar not coherent with the pickup and return times encoded on products. The display of the datepicker is adapted: only display dates. 2 new time selectors are added with the available hours of the linked day. Upgrade PR: https://github.com/odoo/upgrade/pull/9880 task-5083109
Payroll managers can now configure a recurring monthly child bonus directly in an employee's benefits. The amount is automatically reflected in payslip calculations, shown separately on payslips, and included in the relevant net pay, accounting, and withholding tax bases while staying excluded from ONSS.
Original PR description
Before this commit, there was no dedicated way to configure a recurring additional child bonus. Payroll managers had to handle this amount outside the employee's salary package, and it was not automatically included in payslip calculations. After this commit, payroll managers can configure the monthly child bonus from the employee's benefits. Updating the amount triggers a payslip recomputation, and a dedicated salary rule displays the bonus separately on the payslip. The bonus is added to the employee's net-pay and accounting remuneration bases. It is also included in the withholding tax base, while remaining excluded from the ONSS base. Task-6392125
Belgian payroll now makes it easier to monitor voluntary overtime by grouping related entries and adding direct access from employee records. The update also enforces overtime hour limits with validation warnings, helping payroll teams stay compliant and avoid threshold overruns.
Original PR description
Add follow up support for voluntary overtime in Belgian payroll: - Add a salary rule category "Overtime", give it to the overtime time types (VOLOT150/VOLOT200/VOLOTNET and Overtime Belgium) + the voluntary overtime rules - Add a smart button `Overtime` on the employee form view to show all overtime leaves of the employee, grouped by year then by type - Add/adjust the voluntary overtime threshold hours and show a validation error when the employee exceeds the threshold. TaskID: 6048398
Payroll officers now receive warnings on the payroll dashboard when employee data or work schedules may not meet Belgian DMFA requirements. This helps teams correct issues earlier and reduce the risk of payroll reporting blocks later.
Original PR description
In order to aid the payroll officers with their daily tasks and ensure that work schedules and employees personal data are up to the DMFA standards and avoiding any blockings in the future, few warnings have been added to the payroll dashboard. Task: 6299170
Resolved issues and error corrections
When the same delivery order is processed from two open POS sessions at the same time, the system now shows a proper user-facing warning instead of a technical error. This helps staff understand that the order was already printed and avoids confusing error messages during automated Urban Piper order handling.
Original PR description
`* = pos_platform_order, pos_urban_piper` ## Steps to Reproduce: - Install POS Restaurant. - Configure Urban Piper. - Enable "Auto Acknowledge Orders" for a platform(e.g; Zomato) to automatically print delivery orders. - Configure a printer for the POS shop. - Open the same POS session in two different browsers. - Place a test order from Atlas (UrbanPiper). ## Error: `ValueError - This delivery order has already been printed automatically.` ## Cause: When the same delivery order is processed concurrently for both sessions, the backend raises an error when it attempts to print the order again. ## Fix: Replace ValueError with UserError and mark the error message as translatable. sentry-7609743093 Forward-Port-Of: odoo/enterprise#124304
This fix updates Swedish ISO 20022 payment files so they use bank identifiers and party IDs in the format expected by Swedbank. It helps reduce rejected payment files and improves compatibility for Swedish bank payment processing.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125751
Forward-Port-Of: odoo/enterprise#122119Invoices using Brazil's fiscal reform flow now include the required commercial export tax unit conversion factor when sent to Avalara. This helps ensure tax calculations and reporting use the expected quantity conversion data, reducing the risk of invoice processing errors.
Original PR description
This commit adds the comexTaxUnitFactor to the json sent to Avalara when sending an invoice. comexTaxUnitFactor is a factor that convert sales quantity to comexTaxUnit, its value should be the same as cbsIbsUnitFactor. opw-6396462 Forward-Port-Of: odoo/enterprise#125695
The Payroll dashboard no longer crashes when a payroll structure type has no scheduled pay configured. A safe fallback keeps the dashboard available, helping payroll teams avoid disruption from incomplete configuration.
Original PR description
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to…
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to Payroll > Configuration > Settings > Set Payroll Closing Date > Save - Go to Payroll > Configuration > Structure Types > Create a new Structure Type > Unset Scheduled Pay - Open Dashboard Traceback: ```py AttributeError: 'bool' object has no attribute 'title' ``` https://github.com/odoo/enterprise/blob/9a3ea83a432f42f62076a50fca6bc771a2de96bf/hr_payroll/models/hr_payroll_warning.py#L413-L419 The dashboard collects the scheduled pay values from all structure types and later calls ``schedule.title()`` to build the labels. When a Structure Type has no Scheduled Pay configured, so ``schedule`` becomes ``False``, leading to the traceback. ``_get_schedule_pay`` method can return False at [1], So, It will generate the traceback from below line also. https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L401 Solution: Added a fallback value when default scheduled pay is False. [1]: https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L149-L154 sentry-7583037488 Forward-Port-Of: odoo/enterprise#126127 Forward-Port-Of: odoo/enterprise#122492
Ecuadorian electronic invoices that include Special Consumption (ICE) taxes no longer fail during processing. The update ensures the correct tax information is included in the electronic invoice, helping businesses stay compliant and avoid blocked invoice workflows.
Original PR description
Currently, an error occurs when processing Ecuadorian EDI invoices that use taxes from the `Special Consumptions (ICE)` tax group. **Steps to reproduce:** - Install `l10n_ec_edi` and switch to an EC…
Currently, an error occurs when processing Ecuadorian EDI invoices that
use taxes from the `Special Consumptions (ICE)` tax group.
**Steps to reproduce:**
- Install `l10n_ec_edi` and switch to an EC Company.
- Create a new tax with the `Tax Group` set to `Special Consumptions (ICE)`.
- Create an invoice using this tax.
- Confirm the invoice and click `Process Now`.
**Error:**
```
File "/home/odoo/odoo/enterprise/saas-18.4/l10n_ec_edi/models/account_edi_format.py", line 373, in _l10n_ec_get_base_lines
code_percentage = L10N_EC_VAT_SUBTAXES[tax_data['tax'].tax_group_id.l10n_ec_type]
KeyError: 'ice'
```
**Root Cause:**
At [1], non-VAT tax groups such as `ICE` are explicitly not supported
and are not included in `L10N_EC_VAT_SUBTAXES`.
At [2], the code assumes that every Ecuadorian tax group exists in
`L10N_EC_VAT_SUBTAXES` and directly indexes the mapping using
`tax_group_id.l10n_ec_type`. When an invoice uses an `ICE`
tax, causing an error.
**Fix:**
This commit prevents errors by using the tax's `Code ATS` as the
`codigoPorcentaje` value and the tax's `amount` as the `tarifa` in
the XML when the tax group is not present in `L10N_EC_VAT_SUBTAXES`.
(Confirm with the PO [here], just to fix it from 18.4, that the problem is
that it is not working on the versions where we already introduced the feature.)
[1]:
https://github.com/odoo/enterprise/blob/a388b9298268eead53ffa9d33bff7e1927dae33c/l10n_ec_edi/models/account_move.py#L17-L38
[2]:
https://github.com/odoo/enterprise/blob/a388b9298268eead53ffa9d33bff7e1927dae33c/l10n_ec_edi/models/account_edi_format.py#L372-L377
[here]:
https://www.odoo.com/mail/message/1121493378
opw-6373984
opw-6430589
opw-6423812
Forward-Port-Of: odoo/enterprise#123918Restaurant appointment views no longer crash when a table has no linked resource. This helps staff keep using the schedule reliably even when some table setup details are missing.
Original PR description
When a table doesn't have a resource, the appointment_resource_id is undefined and the gantt renderer was crashing when trying to access its id. This commit adds a check to ensure that the appointment_resource_id exists before trying to access its id. Forward-Port-Of: odoo/enterprise#125331
This fixes an automated test for Mexican point of sale invoicing by ensuring an order is fully synchronized before a refund is started. It helps keep validation of the refund workflow stable and reduces false test failures, without changing day-to-day user functionality.
Original PR description
In this commit: =============== - Fix the `test_mx_pos_invoice_order_and_refund` tour, which fails with the warning: `The amount of the order must be positive for a sale and negative for a refund`. - The failure is caused by the refund flow starting before the original order has been fully synced with the backend. - A previous attempt to fix this in odoo/enterprise#109362 by waiting for `FeedbackScreen.isShown()` was not sufficient. Fix: ==== - Add a `Chrome.waitForOrdersSync()` waiting step to the tour to ensure the original order is fully synced before starting the refund flow. Error: 237980 Forward-Port-Of: odoo/enterprise#124948
New contacts assigned a Partner Level now automatically receive a barcode when they are saved. This ensures front desk partnership processes have the needed barcode immediately, avoiding manual fixes or missing access details.
Original PR description
Steps to reproduce: - Go to Contacts. - Create a new contact and assign a Partner Level before saving. - Save the record. Current behavior: - When creating a new contact with a Partner Level, the barcode is not generated automatically. Solution: - Add barcode generation logic to the create() method so that a barcode is automatically generated when a new contact is created with a Partner Level. TaskId-6236375 Forward-Port-Of: odoo/enterprise#125967
Users can now create Google Booking merchant records without errors when the website app is not installed. The change prevents the system from relying on a website-specific field unless it is available, improving reliability for appointment setup.
Original PR description
Currently, an error occurs when a user creates a Google Reserve Merchant record. **Steps to Reproduce:** - Install the `appointment_google_reserve` module. - Go to `Appointments` > `Configuration` >…
Currently, an error occurs when a user creates a Google Reserve Merchant record. **Steps to Reproduce:** - Install the `appointment_google_reserve` module. - Go to `Appointments` > `Configuration` > `Google Booking`. - Click `New` to create a record. `AttributeError: 'website' object has no attribute 'homepage_url'` After this [recent commit], as part of the context-based website resolution refactoring, the `default_website` record is now available even without the `website` module because it is created in `base` [1]. When a user creates a Google Reserve Merchant record, it attempts to set the default URL using the default website from `base`. However, it then tries to access the `homepage_url` field, which is defined in the `website` module [2]. Since the `website` module is not installed, this raises the error [3]. This commit ensures that before accessing `homepage_url`, it first checks whether the `homepage_url` field exists when creating the merchant record, since this field depends on the `website` module. [recent commit]: https://github.com/odoo/odoo/commit/ae81b6f6074632d1a609387e53f97a61ee6c95f4 [1]: https://github.com/odoo/odoo/blob/ea0e2750a43e337bc6d9a00489a30df3fc0616c7/odoo/addons/base/data/website.xml#L5-L9 [2]: https://github.com/odoo/odoo/blob/ea0e2750a43e337bc6d9a00489a30df3fc0616c7/addons/website/models/website.py#L168 [3]- https://github.com/odoo/enterprise/blob/01b0cf4e2f2e2c63c02c3429d029c90639de1322/appointment_google_reserve/models/google_reserve_merchant.py#L21-L22 Task-6395376 sentry-7630852653 Forward-Port-Of: odoo/enterprise#125680
The Accounting reports now handle cases where a grouped tax used on past journal items has later been changed to a regular tax. This prevents the Journal Report from failing and helps users continue reviewing audit data without interruption.
Original PR description
**Steps to reproduce:** - Install account_reports - Create a tax * Tax Computation: Group of Taxes * Definition: [Add a tax] - Create an invoice with that tax - Confirm the invoice - Edit the tax by changing "Tax Computation" to "Percentage" - Go to "Accounting / Reporting / Audit Reports / Journal Report" **Issue:** A KeyError is raised. **Cause:** While generating the data, a group of taxes is found in the journal items. When trying to retrieve its info from the dict listing the groups of taxes, its ID is not found but the system assumes that it's present. opw-6377465 Forward-Port-Of: odoo/enterprise#125291
Saudi payroll now calculates GOSI contributions without incorrectly reducing them for partial periods. This helps ensure payslips and related accounting tests reflect the expected statutory contribution amounts.
Original PR description
task-id: 6380239 Forward-Port-Of: odoo/enterprise#125349 Forward-Port-Of: odoo/enterprise#124122
Hungarian Intrastat tax returns now work with recent changes to the Hungarian tax report structure. This prevents errors during return generation and helps businesses continue submitting Intrastat information reliably.
Original PR description
Here https://github.com/odoo/odoo/pull/253556, we made few changes in the `l10n_hu` report. We basically split some expresions into multiple small one. This has been done for the integration of ec sales list (a60). But hu intrastat was still using the old expressions, leading to an error. This commit aims to adapt the intrastat code to fit with the new a60 expressions. no-task Forward-Port-Of: odoo/enterprise#122662
This fix ensures German POS fiscal transaction cancellations can proceed even when the original active transaction has missing receipt details. It prevents rejection by the fiscal service while keeping existing transaction data unchanged when available.
Original PR description
When cancelling active transactions, the schema was forwarded as-is from the listed transaction. ACTIVE transactions can have an empty schema, and Fiskaly rejects the cancellation PUT with:
{
"code": "E_TX_NO_TYPE_DEFINED",
"message": "`schema.raw.process_type` must be defined for
updating or finishing a transaction",
"status_code": 409,
"error": "Conflict"
}
Fall back to a minimal CANCELLATION receipt schema when the transaction has no schema, while preserving any schema that is already present.
opw-6345005
Forward-Port-Of: odoo/enterprise#122130The AI icon now appears consistently in areas such as Knowledge, Discuss, Website SEO, and Social posting. This fixes a visual issue where the icon could be missing or incorrectly treated as a custom icon, improving clarity for users interacting with AI features.
Original PR description
__Before commit__ Following odoo/enterprise@866597419, the AI icon was not showing in the Knowledge WysiwygArticleHelper because the icon was set in the CSS on the `.oi-ai-logo` elements. __After commit__ The AI icon is now set everywhere using `data-icon="oi-ai-logo"`. <img width="1129" height="530" alt="image" src="https://github.com/user-attachments/assets/572e4d3b-2926-40e8-bfd2-cd6d1aa47e11" /> task-6377407
Payroll decimal precision settings will no longer be reset to default values when the module is upgraded. This protects company-specific payroll configuration and prevents silent loss of user adjustments.
Original PR description
decimal.precision records are user-configurable settings that may be adjusted per company needs. With noupdate="0", every module upgrade resets the 'Payroll' and 'Payroll Rate' precision values back to their defaults, silently discarding any customization made by the user. This is inconsistent with the standard pattern used across Odoo modules. For example, the 'quality' module correctly loads its decimal.precision records with noupdate="1". The same convention is followed in core addons such as 'product' and 'account'. The forcecreate="True" attribute already ensures the records are created on fresh installations, so noupdate="1" only prevents overwriting existing values on upgrade — which is the expected behavior for configuration data. Forward-Port-Of: odoo/enterprise#120509
Fixes an issue where the Payroll dashboard could crash when checking the “Employees Under Minimum Wage” warning for Belgian companies with multiple CP200 employees. This ensures payroll teams can open the dashboard reliably after employee contract changes.
Original PR description
Opening the Payroll dashboard may crashes with an error: - Have a Belgian company with 2 or more CP200 employees having active contracts - Create or modify a contract for at least 2 of them (this marks l10n_be_computed_seniority_years as dirty for the batch) - Open the Payroll dashboard, the "Employees Under Minimum Wage" warning evaluation crashes In _compute_l10n_be_computed_seniority, the for version in cp200_versions loop was incorrectly referencing self instead of version. Since self is the full batch recordset, self.employee_id returns a multi-record set, causing ensure_one() to fail inside _get_first_version_date. task-6358718 Forward-Port-Of: odoo/enterprise#123000
This fix makes status labels in payroll-related dropdown badges readable again, such as states shown on employee forms. It helps users quickly understand record statuses without confusion or visual obstruction.
Original PR description
Users are unable to read the text labels for record states (such as employee form state). This fixes the problem. task-6432088
This fixes a false collaboration error that could appear while automated Knowledge tours were running, even though collaboration was not involved. The change helps keep test results reliable and reduces noise in build validation.
Original PR description
This aims to fix Runbot build error #937788 ([1]) which wasn't fully fixed by commit [2] (see error #944595 ([3])). A collaboration error was thrown during a tour which makes no use of collaboration. Commit [2] made sure the bus from the previous test didn't persist when running this tour so it doesn't interfere, but it didn't fully reset it. [1]: https://runbot.odoo.com/odoo/runbot.build.error/937788 [2]: https://github.com/odoo/enterprise/commit/a6050dd60c587d09443907bdf955805159dbdb2e [3]: https://runbot.odoo.com/odoo/runbot.build.error/944595 Forward-Port-Of: odoo/enterprise#126195
Studio report editing now preserves an empty paragraph when a user deletes its last character. This prevents accidental layout changes and makes report editing behave more predictably, matching the website builder experience.
Original PR description
Problem: In Studio reports, deleting the last character of a paragraph removes the entire paragraph. Cause: `cleanEmptyStructuralContainers` removes the empty paragraph because it is considered empty. Solution: Disable `cleanEmptyStructuralContainers` for reports same as website builder. Steps to reproduce: - Create a new report. - Add multiple paragraphs. - Leave one paragraph with a single character. - Delete the character. - Observe that the paragraph is removed. task-6368965 Forward-Port-Of: odoo/enterprise#126200 Forward-Port-Of: odoo/enterprise#124834
Polish JPK tax exports now use the vendor bill reference in the purchase document field when that reference is available. This helps exported tax files match official guidance and reduces the risk of mismatched purchase documentation during reporting.
Original PR description
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting >…
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting > Reporting > Tax Report and select `This Month`. - From the dropdown, click `JPK` > `Export XML`. - Open the generated XML file and observe the `DowodZakupu` field. **Observation:** `DowodZakupu` contains the vendor `Bill Number` even when a `Bill Reference` is set. **Root Cause:** At [1], `DowodZakupu` is populated only with the vendor `Bill number`(`move_name`) instead of using the `Bill reference`(`ref`) when available. **Fix:** This commit ensures `DowodZakupu` contains the `Bill Reference` when it is available in JPK exports. **Reference:** https://www.podatki.gov.pl/media/eqrn3dey/broszura-jpk_vat-z-deklaracj%C4%85-od-1-lutego-2026-r-en.pdf (page 41) [1]: https://github.com/odoo/enterprise/blob/4b0404058b280136f6865090562f95e18d4d7e0b/l10n_pl_reports/data/jpk_export_templates.xml#L208 opw-6299827 Forward-Port-Of: odoo/enterprise#126113 Forward-Port-Of: odoo/enterprise#121117
This fix ensures Mexican electronic payment documents calculate invoice balances correctly when payments involve exchange rate differences or credit notes. It helps prevent incorrect payment XML values for fully settled invoices, improving tax document accuracy.
Original PR description
### Issue: Attributes of DoctoRelacionado node in the XML display an incorrect value because the exchange rate difference entry distorts the calculation, even though the invoice was fully settled.…
### Issue: Attributes of DoctoRelacionado node in the XML display an incorrect value because the exchange rate difference entry distorts the calculation, even though the invoice was fully settled. https://drive.google.com/file/d/1ntQny0o8bkkfYtY5ZNBK0Yq7Rq0I-yfz/view ### Fix: Sorting partials by "not exchange_move_id" first broke the chronological order whenever the invoice/payment partial itself carried an exchange difference (e.g. a foreign currency payment settled at another rate). This made the residual-chain algorithm consume the credit note's "other_residual" on the wrong payment, so ImpSaldoAnt/ImpPagado/ ImpSaldoInsoluto in the payment CFDI's DoctoRelacionado stayed wrong even though the invoice was fully paid. Populate the exchange move mapping in a separate first pass and sort the partials purely by date/id, so credit notes are always deducted from the correct payment. task-id:[6363092](https://www.odoo.com/odoo/project/49/tasks/6363092) Forward-Port-Of: odoo/enterprise#126061 Forward-Port-Of: odoo/enterprise#124882
Ri.Ba. payment validation now accepts valid San Marino bank accounts in addition to Italian ones. This prevents batch payment validation failures for companies using San Marino IBANs and ensures generated payment files keep the required format.
Original PR description
**_Steps to reproduce :_** - Install l10n_it_riba. - Configure a company with a San Marino (SM) IBAN as the bank account for the journal used for Ri.Ba. - Create a customer payment and add it to a…
**_Steps to reproduce :_** - Install l10n_it_riba. - Configure a company with a San Marino (SM) IBAN as the bank account for the journal used for Ri.Ba. - Create a customer payment and add it to a Batch Payment using the Ri.Ba. payment method. - Validate the Batch Payment. **_Observed behavior :_** The validation fails with the error: `Only bank accounts with an Italian IBAN are allowed to use Ri.Ba. payments` **_Cause :_** The Ri.Ba. validation logic only accepts IBANs with the IT country code and incorrectly rejects valid San Marino (SM) IBANs. **_Fix :_** - Update the Ri.Ba. IBAN validation to accept both Italian (IT) and San Marino (SM) IBANs when generating Ri.Ba. payment files. - While validating Batch Payments for SM IBANs, we observed that the extracted value could overlap with the branch code portion, causing the generated RIBA record to exceed the expected 120-character length. This change updates the extraction logic to prevent overlap and ensure compliance with the required record format. **_opw_** - 6303820 Forward-Port-Of: odoo/enterprise#126208 Forward-Port-Of: odoo/enterprise#121439
Fixed an issue that caused Belgium payroll DMFA reports to fail for student employees. The report now uses the correct student contribution value, helping payroll teams generate required declarations reliably.
Original PR description
[FIX] l10n_be: fix DMFA bug
Bug reproduction:
1 - Go to master → new employee → make it student → joint committee=200
2 - Create payslip -> generate DMFA report
3 - Traceback is there.
Bug cause:
1 - contribution.amount is used for student in DMFA report. 2 - DMFAStudentContribution hasn't amount
2.1 - it has student_contribution_amount field
Bug solution:
1 - Use student_contribution_amount for students instead of amount
task-6410338This update fixes several visual issues where AI and call-related icons could appear misaligned, incorrectly sized, or fail to show in parts of Odoo. Users should see a more consistent interface across AI, Knowledge, Social, Website, Discuss, and VoIP features.
Original PR description
task-6377407
Features or functions removed from Odoo
The old Belgian POS Restaurant fiscalization module has been removed because it is deprecated. Businesses using Belgian blackbox fiscal hardware should move to the replacement module for the newer V2 hardware.
Original PR description
Remove depreciated `pos_blackbox_be` module, which was used for Belgian fiscalization in POS Restaurants. This module is now replaced by `l10n_be_pos_blackbox` in order to operate with the new blackbox V2 hardware.
Code cleanup and technical improvements
This update keeps IoT-related screens and controls aligned with a renamed internal interface in the underlying web framework. It is a technical cleanup that helps maintain compatibility and should not change day-to-day user workflows.
Original PR description
In this commit: - The Owl props API has been renamed to useProps. - Updates the affected IoT-related modules accordingly by renaming imports and replacing `props(...)` with `useProps(...)`. Task:6403054 Community PR : https://github.com/odoo/odoo/pull/278327
This update cleans up AI Website code to match project quality standards without changing business functionality. It helps keep the website-building tools easier to maintain and reduces the risk of small code-quality issues affecting future changes.
This update modernizes parts of online bank synchronization and online payment screens to align with the latest Odoo web framework. It is mainly an internal technical refresh, helping keep banking features reliable and maintainable without introducing notable business workflow changes.
Original PR description
- Replace useService("orm") with usePlugin(ORM)
- Convert account_duplicate_transaction_service into
account_duplicate_transaction_plugin; rename
useCheckDuplicateService -> useCheckDuplicatePlugin
- Replace `static props = {...}` with `props = useProps(...)`
- fetch_missing_transactions_cog_menu uses `orm.unscoped.call` instead
of `orm.call` to keep the RPC alive after component
destruction.
task-6350965This update aligns several enterprise app components with a broader internal restructuring of the communication framework. It should not change day-to-day behavior for users, but it helps keep Approvals, Documents, and Knowledge easier to maintain and evolve.
Original PR description
Enterprise counter-part. https://github.com/odoo/odoo/pull/279133
11 changes
Enhancements to existing features
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364
Original PR description
Steps to reproduce: 1. Create a sales order. 2. Confirm or cancel the order. 3. Share the quotation link. 4. Open the quotation from an incognito window or the customer portal. Issue: - A 'Quotation Viewed by Customer' notification is sent even though the document is no longer an active quotation. Fix: - Only send the notification while the order is in quotation or quotation sent state. opw-6419364
Resolved issues and error corrections
This commit fix the regex used in `street_split` to be more complient. Before: address format was "street_name street_number - street_number2" Now, street_number can be in front of street_name. Format is also less strict, allowing multiple numbers in the street_name without skipping the building number. Linked: https://github.com/odoo/enterprise/pull/121674 task-6317758
Original PR description
This commit fix the regex used in `street_split` to be more complient. Before: address format was "street_name street_number - street_number2" Now, street_number can be in front of street_name. Format is also less strict, allowing multiple numbers in the street_name without skipping the building number. Linked: https://github.com/odoo/enterprise/pull/121674 task-6317758
## Problem `pttExtensionHookService` registers a global `window.addEventListener("message", ...)` handler that reads `data.from` without checking that `data` is defined first: ```js browser.addEventListener("message", ({ data, origin, source }) => { const rtc = env.services["discuss.rtc"]; if ( source !== window || origin !== location.origin || data.from !== "discuss-push-to-talk" || // <- crashes if data is undefined (!rtc && data.type !== "answer-is-
Original PR description
## Problem `pttExtensionHookService` registers a global `window.addEventListener("message", ...)` handler that reads `data.from` without checking that `data` is defined first: ```js…
## Problem
`pttExtensionHookService` registers a global `window.addEventListener("message", ...)`
handler that reads `data.from` without checking that `data` is defined first:
```js
browser.addEventListener("message", ({ data, origin, source }) => {
const rtc = env.services["discuss.rtc"];
if (
source !== window ||
origin !== location.origin ||
data.from !== "discuss-push-to-talk" || // <- crashes if data is undefined
(!rtc && data.type !== "answer-is-enabled")
) {
return;
}
...
```
Any same-window, same-origin `postMessage` sent by an unrelated browser
extension (a common content-script <-> injected-script pattern) can carry
`data === undefined`. The `source !== window` and `origin !== location.origin`
checks only filter out cross-window/cross-origin messages, so a same-origin
message from any other extension reaches this handler and crashes with:
```
TypeError: Cannot read properties of undefined (reading 'from')
```
This surfaces as an uncaught client error on any page with Discuss loaded,
after some time, unrelated to what the user is doing. The Discuss
push-to-talk extension itself does not need to be installed to trigger it,
since the crash happens before checking whether the message actually
originated from that extension.
## Solution
Use optional chaining (`data?.from`) so unrelated same-origin messages with
no `data` are safely ignored instead of crashing.
## Verification
- Reproduced against the live production `web.assets_web.min.js` bundle
(traceback matches exactly).
- Confirmed the bug is still present in the latest `18.0` of both `OCA/OCB`
and `odoo/odoo` (no newer commit touches this file since
`dc58ef1ad904`, which fixes an unrelated issue).Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never fol
Original PR description
Before this commit, the unread banner could stop showing in a channel until it was left and opened again: - open a channel with unread messages - click "Mark as Read" - read the same channel from another device - receive a new message: the server counter increases, still no banner This happens because an implicit mark as read freezes the local unread state, so the banner stays in place while the user reads. The problem is that it stays frozen even after the banner is gone, and never follows the server counter again. This commit freezes that state only while something is still unread locally. This also fixes the flaky test "no unread message banner after message is deleted". https://runbot.odoo.com/odoo/error/242776
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an ordinary settlement, not a deposit, but the code recognized it as one anyway. The values reported for `PrepaidAmount` were wrong regardless of the invoice date, and for a fully paid invoice this also collapsed `PayableAmount` to 0.00, which LHDN rejects. Root Cause: LHDN only considers a reconciled
Original PR description
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an…
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an ordinary settlement, not a deposit, but the code recognized it as one anyway. The values reported for `PrepaidAmount` were wrong regardless of the invoice date, and for a fully paid invoice this also collapsed `PayableAmount` to 0.00, which LHDN rejects. Root Cause: LHDN only considers a reconciled payment a genuine deposit if it was received before the invoice date. The code applied no date condition at all, so any payment reconciled against the invoice was added to `PrepaidAmount` and reduced `PayableAmount` accordingly. Fix: Only sum reconciled payment partials whose date is strictly earlier than the invoice date as prepaid, so regular payments are no longer misclassified as deposits. As a safety net, if the valid prepaid sum still covers the full invoice amount (e.g. a full advance payment), reset it to 0 so `PayableAmount` always reflects the full amount_total instead of being reported as 0. Also omit the `PrepaidPayment` node entirely when there is no genuine prepayment, rather than emitting it with a 0.00 amount. [Task-6404296](https://www.odoo.com/odoo/my-tasks/6404296) Forward-Port-Of: odoo/odoo#278010
Purpose of this PR: - On double click, opening the toolbar is delayed by 300ms to prevent flickering before a potential triple click. - However, mouseup was re-enabling selection tracking (onSelectionChangeActive = true) before the 300ms delay finished. Because browser selectionchange events are dispatched asynchronously after mouseup, they triggered updateToolbar() immediately, bypassing the 300ms delay. - This fix re-enables selection tracking only after the 300ms debounced update actuall
Original PR description
Purpose of this PR: - On double click, opening the toolbar is delayed by 300ms to prevent flickering before a potential triple click. - However, mouseup was re-enabling selection tracking (onSelectionChangeActive = true) before the 300ms delay finished. Because browser selectionchange events are dispatched asynchronously after mouseup, they triggered updateToolbar() immediately, bypassing the 300ms delay. - This fix re-enables selection tracking only after the 300ms debounced update actually finishes. runbot-941543 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatte
Original PR description
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also…
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatter(ignore_record_keys=[])` The purpose was to be able to easily include all keys and ignore the default ingnore list, but this makes the additional blacklisting of a few keys more tedious, and the general usage and implementation more complex `JSONFormatter(ignore_record_keys=[*JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS, 'other key'])` To simplify the logic, **this is not the case anymore**, so to include all keys something like this would be needed `JSONFormatter(additional_record_keys=JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS)` Or an hardcoded list. Forward-Port-Of: odoo/odoo#279049
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1- Create two auto detect fiscal positions: France, Germany 2- Set portal user's partner address country to France. 3- Using portal user, shop from website, and create a delivery address. 4- Pay and confirm the order. 5- Using the admin user, you check the SO's FP which is correctly set to
Original PR description
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1-…
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1- Create two auto detect fiscal positions: France, Germany 2- Set portal user's partner address country to France. 3- Using portal user, shop from website, and create a delivery address. 4- Pay and confirm the order. 5- Using the admin user, you check the SO's FP which is correctly set to Germany. 6- Using portal user, again shop from website, and don't change address. Keep previous shipping address which is Germany. 7- Confirm and pay the order. 8- Using admin user, check the new SO's FP. It's set to France. Cause: --- `_compute_fiscal_position_id` in SO depends on `partner_shipping_id`. When the `partner_shipping_id` is not changed, the fiscal position value set in create will remain. This value is set in `Website._prepare_sale_order_values()`. The `fiscal_position_id` is set to self.fiscal_position_id, which is `_get_fiscal_position(self.env.user.partner_id)`. Fix: --- If the user has already a SO, we can use last SO's shipping address and invoice address to calculate FP in `_prepare_sale_order_values`. opw-6357638 Forward-Port-Of: odoo/odoo#276485
- `s_three_columns` cards could end up with mismatched heights: `equalizeCardHeights` now measures header height directly instead of deriving it from the already-stretched card container. - Links appeared with a black background: exclude `btn-link` from background-color application. - Background images didn't stretch: pass `preserve_comments` so the DPI-scaling fix comment isn't stripped from the sent email. opw-6044725 --- I confirm I have signed the CLA and read the PR guidelines at w
Original PR description
- `s_three_columns` cards could end up with mismatched heights: `equalizeCardHeights` now measures header height directly instead of deriving it from the already-stretched card container. - Links appeared with a black background: exclude `btn-link` from background-color application. - Background images didn't stretch: pass `preserve_comments` so the DPI-scaling fix comment isn't stripped from the sent email. opw-6044725 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279196 Forward-Port-Of: odoo/odoo#278862
Miscellaneous changes
**Steps to reproduce:** - Install Survey app - Create a survey - Share as e-mail - Add some text in the body/subject - Modify recipients - The added text is automatically reset **Issue:** Behavior was previously introduced to match the content of the composer body/subject to the recipient language. If there was only one language among the recipients it automatically adapted the template and changed the rendered language (which also refreshed the content). This logic was trigge
Original PR description
**Steps to reproduce:** - Install Survey app - Create a survey - Share as e-mail - Add some text in the body/subject - Modify recipients - The added text is automatically reset **Issue:** Behavior…
**Steps to reproduce:** - Install Survey app - Create a survey - Share as e-mail - Add some text in the body/subject - Modify recipients - The added text is automatically reset **Issue:** Behavior was previously introduced to match the content of the composer body/subject to the recipient language. If there was only one language among the recipients it automatically adapted the template and changed the rendered language (which also refreshed the content). This logic was triggered by a depends on `partner_ids` and triggered the compute on every recipient changes which led to the subject/body reset. **Fix:** Revert commit: https://github.com/odoo/odoo/commit/b7bbb7b21f4848323666230b518cad9459726f67 in 18.0+ Also adapt commit: https://github.com/odoo/odoo/commit/c6f19e89cb6019e7dbaadbc7427fbb6ddd5661ed to avoid mixed language in resulting mail when the composer was modified We could also try to prevent the compute when the subject or body is already modified instead of removing its logic. opw-6020245
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266397 Forward-Port-Of: odoo/odoo#279414
Original PR description
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266397 Forward-Port-Of: odoo/odoo#279414
3 changes
Resolved issues and error corrections
When a manufacturing order consumes components into negative stock and a later receipt revalues those component moves, only the component valuation was corrected. The finished product kept its initial cost and the production account stayed unbalanced. Steps to reproduce: ------------------- * Configure a finished product and a component in AVCO with automated or manual inventory valuation * Add a BoM with 10 components per finished product * Purchase and receive 5 components at $5/unit *
Original PR description
When a manufacturing order consumes components into negative stock and a later receipt revalues those component moves, only the component valuation was corrected. The finished product kept its…
When a manufacturing order consumes components into negative stock and a later receipt revalues those component moves, only the component valuation was corrected. The finished product kept its initial cost and the production account stayed unbalanced. Steps to reproduce: ------------------- * Configure a finished product and a component in AVCO with automated or manual inventory valuation * Add a BoM with 10 components per finished product * Purchase and receive 5 components at $5/unit * Manufacture 1 finished product, forcing consumption of 10 components * Purchase and receive at least 5 more components at $10/unit > Observation: A revaluation entry is created on the component move of the MO (e.g. 0 qty, -$25), but no matching revaluation is created on the finished product. The FG stays valued at $50 instead of $75 and the WIP/production account is not balanced. Why the fix: ------------ FIFO vacuum corrections were only propagated through `_post_fifo_vacuum` for real-time valuation layers. Manual periodic vacuum SVLs were ignored, so the MRP hook never ran for the common test and production setups. Pass manual and real-time vacuum SVLs to the hook, and mirror the component correction onto the finished product move of the related done MO. opw-6232734
Steps to reproduce: - Install employees and attendance app - Make sure there are 2 companies - Make user's employee record for Company B, but not A - Make company A the default company for user - Enable "attendances from backend" setting - Click on the attendance dot (systray) Current Behavior: The dot disappears and you can't check in Expected Behavior: You are able to check in Other bug scenario: If you have employee records in both Company A and Company B, you can check in.
Original PR description
Steps to reproduce: - Install employees and attendance app - Make sure there are 2 companies - Make user's employee record for Company B, but not A - Make company A the default company for user - Enable "attendances from backend" setting - Click on the attendance dot (systray) Current Behavior: The dot disappears and you can't check in Expected Behavior: You are able to check in Other bug scenario: If you have employee records in both Company A and Company B, you can check in. However, you can never check in for Company B as the default company is always selected in the server code opw-6392301
Before this fix, if a pivot table with comparison was inserted, it would not be displayed correctly in the spreadsheet. After this fix, the comparison is completely ignored when inserting a pivot into a spreadsheet. The domain of the comparison is ignored too. Task: 6429681 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Before this fix, if a pivot table with comparison was inserted, it would not be displayed correctly in the spreadsheet. After this fix, the comparison is completely ignored when inserting a pivot into a spreadsheet. The domain of the comparison is ignored too. Task: 6429681 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr