Daily updates from Odoo
Wednesday, July 15, 2026
83 changes
4 changes
New functionality added to Odoo
This update adds the functionality to automatically generate Taiwan E-invoices from point of sale orders. It ensures that necessary data is passed from the POS system to the invoice, streamlining the e-invoicing process for businesses operating in Taiwan. This improves compliance and simplifies record-keeping.
Original PR description
This module adds extra functions on the point of sale for l10n_tw_edi_ecpay, passing values from pos order to invoice for creating Taiwan E-invoice task-5122414 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255980
Enhancements to existing features
Marketing automation now has stronger test coverage and targeted fixes for campaign synchronization, user-triggered activity scheduling, and failed or bounced message handling. This helps ensure participants receive the right follow-up actions at the right time across email, SMS, and WhatsApp campaigns, while also preparing the app for future performance improvements.
Original PR description
RATIONALE In order to prepare upcoming improvements for marketing automation application, as well as performance improvements, some tests are added to improve coverage and cover some synchronization…
RATIONALE
In order to prepare upcoming improvements for marketing automation
application, as well as performance improvements, some tests are added
to improve coverage and cover some synchronization use cases.
SPECIFICATIONS
Add some tests improve coverage of synchronization, as we recently
discovered limitations
* "opposite" triggers when checking brother traces to skip in
'action_update_participants' (which synchronizes traces): sub
addons (sms, whatsapp) is not taken into account;
* 'schedule_date' is not correct for user-based activities (e.g.
mail_open, mail_click, ...) when new activities are added to
a campaign. They should not have scheduled dates, as it depends
on user action. Date is correct for activities when participants
enter child activities but not when doing the synchronize;
* add some checks on participant state;
* globally try to improve some corner cases coverage;
Add some tests to improve coverage of bounce / fail behavior with
various activities, as we want to make it clearer how MA should
behave when dealing with issue. First step is to assert current
behavior and fix some odd bits.
Notably in some cases trace update is missing, notably with SMS
sending with does not call trace update method, which means some
triggers are not processed.
Various fixes are included in this branch, spotted by newly added tests.
See commits for more details.
Task-4224152: [marketing_automation] Performance / Scalability
Forward-Port-Of: odoo/enterprise#124248
Forward-Port-Of: odoo/enterprise#124126Resolved issues and error corrections
Automatic bank reconciliation now gives failed statement lines one more try before excluding them. This helps avoid losing reconciliation work when a temporary issue, such as a database conflict, causes the first attempt to fail.
Original PR description
The auto reconcile cron drops the lines whenever they raise an error which is an issue for things like serialization errors. Now the code retries failed lines once before dropping them to make sure it's an issue with the lines. task-6273202 Forward-Port-Of: odoo/enterprise#119383
This fixes how Belgian payroll determines the date boundaries used to calculate eco vouchers. It helps ensure employees receive the correct voucher entitlement for the relevant payroll period and reduces payroll correction work.
Original PR description
Forward-Port-Of: odoo/enterprise#124073 Forward-Port-Of: odoo/enterprise#120166
6 changes
New functionality added to Odoo
This update adds functionality to seamlessly integrate with Taiwan's E-invoice system for point-of-sale transactions. It automatically transfers relevant data from the POS order to the invoice, simplifying the e-invoice creation process and ensuring compliance with local regulations. This improves the user experience for businesses operating in Taiwan.
Original PR description
This module adds extra functions on the point of sale for l10n_tw_edi_ecpay, passing values from pos order to invoice for creating Taiwan E-invoice task-5122414 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255980
Enhancements to existing features
The Mexican payroll localization now includes the latest SAT payroll perception and deduction concepts used for CFDI reporting. This helps businesses keep payroll documents aligned with current Mexican tax authority requirements.
Original PR description
Adds the new SAT perception and deduction concepts to the Mexican payroll CFDI concept catalog. task-6295124 Forward-Port-Of: odoo/enterprise#121568
Resolved issues and error corrections
This fix prevents payroll screens from crashing when users add Daily Salary or Integration Factor fields to Mexican payslip forms with Odoo Studio. It ensures these values are only calculated once the needed employee and contract details are available, so users can create off-cycle payslips and review salary information safely.
Original PR description
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule…
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule computations. However, doing so raises a traceback immediately upon closing the Studio editor, as well as when attempting to create a new Off-Cycle payslip.
### Steps to reproduce:
* Install `l10n_mx_hr_payroll` and `web_studio`.
* Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company.
* Go to Payroll > Payslips > Payslips and create a "New Off-Cycle"
* Use the Studio editor to add `l10n_mx_daily_salary` or `l10n_mx_integration_factor` fields.
* Close the Studio editor.
### Current behavior:
A traceback is raised depending on the field added
#### For the Daily Salary field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 21, in _compute_daily_salary
payslip.l10n_mx_daily_salary = payslip.version_id.wage / payslip._rule_parameter('l10n_mx_schedule_table')[payslip.version_id.schedule_pay]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: False
```
#### For the Integration Factor field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 33, in _compute_integration_factor
payslip.employee_id.with_context(before_date=payslip.date_from)._get_first_contract_date()
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 493, in _get_first_contract_date
versions = self._get_first_versions_filtered(no_gap=no_gap).filtered(lambda x: x.contract_date_start)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 461, in _get_first_versions_filtered
self.ensure_one()
File "/Users/ivgm/odev/worktrees/19.0/odoo/odoo/orm/models.py", line 5942, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: hr.employee()
```
### Expected behavior:
No error is raised, and the fields are correctly displayed on the form view.
### Solution:
* Add Guard Clause: When creating a "New Off-Cycle" payslip, `payslip.version_id` is not initially set because no employee has been selected yet. Added a condition to check if `version_id` exists before computing the values to prevent the traceback.
* View Update: Since displaying these fields is a highly requested feature for traceability, they have now been added to the form view.
target: 19.0
task-6267003
Forward-Port-Of: odoo/enterprise#121718Automatic bank statement reconciliation now gives failed lines one retry before excluding them. This helps avoid losing items because of temporary system issues, improving reliability for accounting teams.
Original PR description
The auto reconcile cron drops the lines whenever they raise an error which is an issue for things like serialization errors. Now the code retries failed lines once before dropping them to make sure it's an issue with the lines. task-6273202 Forward-Port-Of: odoo/enterprise#119383
Rental pickup and return receipts now include the separate invoicing and shipping address details when customer addresses are enabled. This prevents missing address information on customer-facing rental documents and helps ensure deliveries, returns, and billing are handled with the right contact details.
Original PR description
**Steps to Reproduce:** 1. Install sale_renting and enable "Customer Addresses" in the settings 2. Confirm a rental order with shipping address and invoice address 3. Print the Pickup and Return Receipt **Issue:** Only the general partner address is printed; the invoicing/shipping `information_block` is missing **Why this happens:** The 19.2 layout rework (abf18ba250bae2f390f93f70abef1d7fb601c524) switched `web.external_layout` calls to accept macro arguments (e.g. `address="address"`). report_rental_order_document was only partially migrated: `address` was set above the t-call and passed as an argument, but `information_block` was left as a t-set inside the call body, which was the old convention. Once external_layout is called with explicit arguments, content t-set nodes in the body no longer populate the callee's scope, so address_layout's `t-if="information_block"` never triggers. opw-6366091 Forward-Port-Of: odoo/enterprise#124077
Opening the manufacturing planning view now ignores maintenance requests with incomplete scheduling information instead of failing. This prevents a blocking error for planners when a maintenance request has an end date but no start date.
Original PR description
#### Issue: Opening the MRP planning view could raise a traceback when a maintenance request had a ``Scheduled End`` but no ``Scheduled Date``. ```TypeError: '<' not supported between instances of 'NoneType' and 'datetime.datetime'``` #### Cause: In `_get_maintenances_intervals`, `mrp_maintenance` loaded maintenance intervals for gantt unavailability without filtering out incomplete rows. If an interval like False, datetime reached Intervals, it crashed when comparing None with a datetime. #### Fix: Filter out incomplete maintenance intervals in the gantt query. Also added a constraint on `maintenance.request` to require `schedule_date` and `schedule_end` to either both be set or both be empty in this community PR: https://github.com/odoo/odoo/pull/265208 opw-6225772 Forward-Port-Of: odoo/enterprise#117710
9 changes
Enhancements to existing features
The timesheet timer menu now opens with fewer delays by reusing already available information and avoiding unnecessary server calls. This makes daily time tracking feel quicker and smoother for employees, especially when the menu is opened often.
Original PR description
This PR removes some blocking RPC calls and caches information to make the loading of the systray as lightweight as possible. Changes include: - Move `field_get` to the lazy session info, so the field metadata is available client-side without a dedicated round-trip. - Cache the pre-filled form: it does not change as long as the task / project context stays the same, so it is computed once and reused. - Drop the `get_server_time` RPC and rely on the client-side clock. - Add a client-side systray cache service to avoid redundant requests. Task-6131386
Resolved issues and error corrections
The automated bank reconciliation process now gives failed items one more attempt before discarding them. This helps avoid losing reconciliation work when a temporary system issue, such as a database conflict, causes a first attempt to fail.
Original PR description
The auto reconcile cron drops the lines whenever they raise an error which is an issue for things like serialization errors. Now the code retries failed lines once before dropping them to make sure it's an issue with the lines. task-6273202 Forward-Port-Of: odoo/enterprise#119383
Hong Kong IRD payroll reports now use the correct tax year based on an employee's start or leaving date. The change also ensures required departure reasons are included, helping companies avoid rejected IRD submissions during certification or filing.
Original PR description
As we now have complete support for IRD reports (in master), we started to try to get our system certified by the IRD.
A first submission highlighted a few issues that we are now fixing.
From 19.0:
- In IR56F, the RTN_ASS_YR should be the tax year in which the employee left the company. E.g. after april, the next year.
- In the same report, if the code for the cessation reason is 5 (other), the reason MUST be provided.
From 19.2:
- Same change has to be done when setting RTN_ASS_YR for IR56G
- A same change has to also be done for IR56E, based on the date the employee joined the company.
task-6332150
Forward-Port-Of: odoo/enterprise#124167
Forward-Port-Of: odoo/enterprise#121877This fix prevents the AI chat from crashing in screens where some action details are unavailable, such as Physical Inventory. Users can now ask AI questions from those views without hitting an error, improving reliability in day-to-day inventory workflows.
Original PR description
Steps to reproduce: ------------------------------------ 1. Go to Inventory>Operation> Physical Inventory. 2. Open the AI chat . 3. Ask the AI any question (e.g. Filtered entries with lot number 0005.). Observation: ------------------------------------ The AI request fails with the following error: RPC_ERROR 'NoneType' object has no attribute 'browse' Issue: ------------------------------------ When building the AI session context, the code assumes that `current_view_info` always contains an `action_id`. For this views, `action_id` is not present. As a result, `self.env.get(action.type)` returns `None`, and the subsequent call to `.browse()` raises a error, preventing the AI request from being processed. Solution: ------------------------------------ Validate that `action_id` exists and that the corresponding action record is valid before retrieving the current action and its search view. opw-6365175
This fix prevents the Belgian payroll app from failing during installation when required setup data is not loaded yet. It allows installations to continue normally on populated databases, reducing disruption for customers enabling the payroll module.
Original PR description
Currently during the installation process the compute is called before the data of the module is loaded. The compute uses a env.ref that searches for an external id that will only exist later on. this creates a traceback in populated databases, since the compute will be processed, and the app won't be installed. Here we cannot overwrite the auto_init since the field is not stored The only option left was to adapt the comupte to not throw a traceback in case the fields are not found, and instead proceed with the compute/installation opw-6340800
This fixes an issue where attendee emails could show an outdated event start date after a multi-day event was rescheduled. Event registration details now refresh correctly when event dates change, helping avoid confusing or incorrect communications to attendees.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date` to recompute value on changing the date of the event opw-6284576 Forward-Port-Of: odoo/enterprise#120184
This update fixes an issue where online payments with cash rounding weren't calculating correctly. Now, when an order includes cash payments and cash rounding is enabled, the system accurately requests the correct online payment amount and properly marks the order as paid. This ensures accurate financial reporting and a smoother checkout experience for customers.
Original PR description
…nding When cash rounding is enabled with "Only for cash payment methods", an order partially paid in cash and completed with an online payment could neither request the correct online amount nor be…
…nding When cash rounding is enabled with "Only for cash payment methods", an order partially paid in cash and completed with an online payment could neither request the correct online amount nor be marked as paid. Steps to reproduce: - Enable cash rounding (e.g. 0.05, HALF-UP) with "Only for cash payment methods" - Create an order with a total of 15.28 - Add a cash payment of 10.00, then an online payment for the remainder The frontend requests 5.28 for the online payment, but as soon as the order contained a cash payment the server rounded the whole order total: get_and_set_online_payments_data() returned an unpaid amount of 5.30 (15.30 - 10.00), so the validation failed with "Invalid online payments". Even once the online payment of 5.28 was processed, the order remained stuck in draft with the money captured: _is_pos_order_paid() compared the paid amount (15.28) against the rounded total (15.30). Only the part of the order actually settled in cash must be rounded: non-cash payments (card, online, ...) always pay their exact share. - get_amount_unpaid() now returns the exact residual of the order when the rounding only applies to cash payment methods. - _get_rounded_amount() now only rounds the amount not covered by non-cash payments, resolving its old TODO. Cash-only orders and orders where the cash payment settles the rounded remainder are unaffected. opw-6314690 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275305
This update resolves a crash in Point of Sale (PoS) when settling sales orders after archiving product attributes. Previously, archiving a product attribute alongside a sale order could cause an error. This change ensures PoS settlement remains stable and reliable, even when product attributes are archived.
Original PR description
When a product attribute line is used in a confirmed sale order, Odoo archives it (active=False) instead of deleting it when removed from the product template. If the corresponding product.attribute record is also archived, settling that sale order in PoS crashes with: TypeError: Cannot read properties of undefined (reading 'create_variant') opw-6315766 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274484 Forward-Port-Of: odoo/odoo#271778
Features or functions removed from Odoo
This pull request reverses a recent change to Belgian salary contract mobility budget calculations. The update is being held back from this version so key users can validate it first in the main development version before it reaches this release line.
Original PR description
This reverts commit [692ecf81fe97d86d2f3196456dbb57ced90fe83c.](https://github.com/odoo/enterprise/pull/109845) Mobility budget should be done in master only to allow pre-testing by key users Task-6389002
8 changes
New functionality added to Odoo
This update adds functionality to seamlessly integrate with Taiwan's E-invoice system. It now automatically transfers relevant data from point-of-sale orders to the corresponding invoices, simplifying the process for businesses operating in Taiwan and ensuring compliance with local regulations.
Original PR description
This module adds extra functions on the point of sale for l10n_tw_edi_ecpay, passing values from pos order to invoice for creating Taiwan E-invoice task-5122414 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255980
Enhancements to existing features
The Mexican payroll localization now includes the latest SAT perception and deduction concepts in the CFDI payroll catalog. This helps businesses keep payroll reporting aligned with current Mexican tax authority requirements.
Original PR description
Adds the new SAT perception and deduction concepts to the Mexican payroll CFDI concept catalog. task-6295124
Resolved issues and error corrections
This fixes an error that could appear when payroll users added Daily Salary or Integration Factor fields to payslip forms with Odoo Studio. The fields can now be displayed safely before an employee or contract version is selected, helping users verify payroll calculations without interruptions.
Original PR description
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule…
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule computations. However, doing so raises a traceback immediately upon closing the Studio editor, as well as when attempting to create a new Off-Cycle payslip.
### Steps to reproduce:
* Install `l10n_mx_hr_payroll` and `web_studio`.
* Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company.
* Go to Payroll > Payslips > Payslips and create a "New Off-Cycle"
* Use the Studio editor to add `l10n_mx_daily_salary` or `l10n_mx_integration_factor` fields.
* Close the Studio editor.
### Current behavior:
A traceback is raised depending on the field added
#### For the Daily Salary field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 21, in _compute_daily_salary
payslip.l10n_mx_daily_salary = payslip.version_id.wage / payslip._rule_parameter('l10n_mx_schedule_table')[payslip.version_id.schedule_pay]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: False
```
#### For the Integration Factor field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 33, in _compute_integration_factor
payslip.employee_id.with_context(before_date=payslip.date_from)._get_first_contract_date()
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 493, in _get_first_contract_date
versions = self._get_first_versions_filtered(no_gap=no_gap).filtered(lambda x: x.contract_date_start)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 461, in _get_first_versions_filtered
self.ensure_one()
File "/Users/ivgm/odev/worktrees/19.0/odoo/odoo/orm/models.py", line 5942, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: hr.employee()
```
### Expected behavior:
No error is raised, and the fields are correctly displayed on the form view.
### Solution:
* Add Guard Clause: When creating a "New Off-Cycle" payslip, `payslip.version_id` is not initially set because no employee has been selected yet. Added a condition to check if `version_id` exists before computing the values to prevent the traceback.
* View Update: Since displaying these fields is a highly requested feature for traceability, they have now been added to the form view.
target: 19.0
task-6267003
Forward-Port-Of: odoo/enterprise#121718Regular employees can now open the Attendance Gantt view even when coworkers with fully flexible schedules have approved time off. This prevents an access error and keeps attendance planning usable without exposing restricted time-off records.
Original PR description
When a regular employee accesses the Attendance Gantt view, they encounter an AccessError if there are other employees with flexible schedules who have taken time off. ### **Steps to reproduce:** -…
When a regular employee accesses the Attendance Gantt view, they encounter an AccessError if there are other employees with flexible schedules who have taken time off. ### **Steps to reproduce:** - Install hr_holidays, hr_attendance with demo. - Create a time off and validate for an employee, and set the employee's contract to fully flexible - As demo user, go to the attendance app. ### **Error:** ``` odoo.exceptions.AccessError: Sorry, Marc Demo doesn't have 'read' access to: - Time Off (hr.leave) ``` ### **Root cause:** since [this commit](https://github.com/odoo/enterprise/pull/112482/changes/b326263d67dc0654a7d4b6d77dc4ad8de53bc1c1), `handle_flexible_leave_interval` accesses fields on `leave.holiday_id` at [1] to determine the bounds of flexible leave intervals. when the unavailability computation is performed by a regular employee, they may not have access to the corresponding `leave` record leading to access error. [1]- https://github.com/odoo/enterprise/blob/7a34c9a6a58df22fbef143d820a29106249e3af5/hr_holidays_gantt/models/resource_calendar.py#L17-L24 ### **Fix:** This commit allows regular employees to compute unavailability intervals for flexible employees. **opw-6243778** Forward-Port-Of: odoo/enterprise#119229
The automatic bank statement reconciliation process now retries lines that fail once before excluding them. This helps avoid losing reconciliation work due to temporary system issues, improving reliability for accounting teams.
Original PR description
The auto reconcile cron drops the lines whenever they raise an error which is an issue for things like serialization errors. Now the code retries failed lines once before dropping them to make sure it's an issue with the lines. task-6273202 Forward-Port-Of: odoo/enterprise#119383
Indian GST reports now better reflect current legal requirements for imports. Import of services is no longer shown in GSTR-2B, and GSTR-3B reporting has been adjusted for updated import sections for goods and services.
Original PR description
As per the law, import of services is not required to be shown in GSTR-2B. Therefore, the related report lines are removed in this commit. Additionally, GSTR-3B reporting is now handled according to the updated section changes for import of goods and services. task-6330737 Forward-Port-Of: odoo/enterprise#121925
When event dates are changed, attendee email content now reflects the latest start date instead of showing outdated information. This helps avoid sending incorrect event schedules to participants after rescheduling.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date` to recompute value on changing the date of the event opw-6284576 Forward-Port-Of: odoo/enterprise#120184
This fix ensures Saudi GOSI contributions are calculated on the full eligible amount rather than being prorated. This helps payroll teams produce more accurate payslips and reduces the risk of incorrect social insurance reporting.
Original PR description
task-id: 6380239 Forward-Port-Of: odoo/enterprise#124122
3 changes
Resolved issues and error corrections
This fixes an issue where payroll rule parameter data could be unintentionally changed after being reused from cache. The change helps keep payroll calculations and related HR payroll behavior consistent and avoids hard-to-trace errors.
Original PR description
Cached functions with `@ormcache` should not return immutable values, yet `_get_parameter_from_code()` could return dicts/sets/lists/etc. It could lead to very obscure bugs such as: ```python def…
Cached functions with `@ormcache` should not return immutable values, yet `_get_parameter_from_code()` could return dicts/sets/lists/etc.
It could lead to very obscure bugs such as:
```python
def some_innocent_code():
category_dict = self.env["hr.rule.parameter"]._get_parameter_from_code('l10n_be_work_entry_categories')
incapacity_codes = category_dict['partial_incapacity']
incapacity_codes |= category_dict['total_incapacity']
# ... then use incapacity_codes
def print_rule_param():
print(self.env["hr.rule.parameter"]._get_parameter_from_code('l10n_be_work_entry_categories')['partial_incapacity'])
print_rule_param() # OrderedSet(['LEAVE281'])
some_innocent_code()
print_rule_param() # OrderedSet(['LEAVE281', 'LEAVE264', 'LEAVE266', 'LEAVE217', 'LEAVE218', 'LEAVE219', 'MEDIC01'])
```
The solution was to either deepcopy the returned value each time, or to change all the rule parameters to their frozen equivalent. Since we don't have access to frozen objects in rule parameters's xml definitions, we opted for the deepcopy approach.
task-6329380
Forward-Port-Of: odoo/enterprise#124141
Forward-Port-Of: odoo/enterprise#123057Fixed an issue where attendee emails could show an outdated event start date after a multi-day event was rescheduled. This ensures communications sent to attendees reflect the latest event schedule, reducing confusion for organizers and participants.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date` to recompute value on changing the date of the event opw-6284576 Forward-Port-Of: odoo/enterprise#120184
Colombian electronic invoice imports now treat the price in DIAN XML files as the actual unit price instead of dividing it by the base quantity. This prevents incorrect negative discounts on vendor bills when imported products have quantities greater than one.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466 Forward-Port-Of: odoo/enterprise#122313
5 changes
Enhancements to existing features
This update ensures Peruvian e-invoices can include the product codes required by SUNAT's new 2026 validation rules. It adds missing shared product classification codes and activates Peru-specific codes only for databases using the Peru localization, reducing the risk of invoice rejection for affected goods.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124001 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
This fix prevents an error when users leave Studio with the browser Back button after editing a project task view. Users can now return smoothly to the task list without crashes or repeated navigation loops.
Original PR description
### Steps to reproduce: 1. Open any Project > open its Tasks view 2. Open Studio 3. Press the browser Back button ### Current behavior: Crash "active_id is not defined". The Tasks view needs…
### Steps to reproduce: 1. Open any Project > open its Tasks view 2. Open Studio 3. Press the browser Back button ### Current behavior: Crash "active_id is not defined". The Tasks view needs active_id (the ID of the open project, e.g. 5) to pre-filter tasks by project, but it is missing when Studio restores the view from the URL. ### Expected behavior: Back exits Studio and returns to the Tasks view with no error. ### Issue: The browser URL tracks navigation as a stack of visited actions. When Studio is open, the stack has two entries: the view being edited (position -2) and Studio itself (position -1). Studio loads the action from position -2 but was reading active_id from position -1 Studio's own slot, which carries no record ID. Reading context from the wrong slot left active_id undefined, crashing the view render. A second problem: Studio was writing active_id into the shared URL state. The router automatically copies this into the Studio URL path, changing ".../tasks/studio" to ".../tasks/5/studio". Every Back press produced a different URL, so the router treated it as a new visit instead of a Back navigation creating an infinite history loop. ### Fix: active_id now comes from the same URL slot as the action identity (position -2), which is where the project ID actually lives. The shared URL write that caused the history loop is removed. task-6097949
Email buttons for appointments now use the website tied to the appointment setup instead of falling back to the last logged-in website or default site. This prevents customers in multi-website environments from being sent to the wrong website when managing their appointment.
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from…
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. Case 1: - Have website A and website B - Create an appointment page website A - Log in via website B - As public user, make an appointment in Website A - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the appointment. This occurs because when an user log in, the system parameter 'web.base_url' is updated with the current url. This parameter is then used as fallback when we need to retrieve the base url without an active record Case 2: - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) Backport with improvements of 15bae202d8f1b5bf70bbc63b2d89025e9237e6cf opw-4146760 opw-4336369 Forward-Port-Of: odoo/enterprise#123851 Forward-Port-Of: odoo/enterprise#122669
This fix updates POS IoT device matching so newer IoT Boxes are found even when they no longer provide subtype or manufacturer details. This helps printers and payment terminals connect more reliably without requiring missing device information.
Original PR description
Newer IoT Boxes don't share device subtype or manufacturer. We then adapt the domains to avoid searching on fields that aren't filled. task-6388669 task-6388733 Forward-Port-Of: odoo/enterprise#124306
Colombian electronic invoice imports now treat the XML price value as the actual unit price, matching DIAN rules. This prevents incorrect negative discounts on vendor bills when imported invoice lines use quantities greater than one.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466 Forward-Port-Of: odoo/enterprise#122313
32 changes
New functionality added to Odoo
Mexican payroll users can now see key salary values used in payslip calculations, making it easier to validate results. The integration factor can also be adjusted manually when there is not enough historical data, helping ensure correct IMSS contribution setup for new customers.
Original PR description
The daily salary and the integration factor (`l10n_mx_daily_salary` and `l10n_mx_integration_factor`) are two fields used during the payslip computation. Displaying these fields helps users to validate the calculations. Furthermore, when a new customer configures payslips for the first time, there is no historical data in the database to compute the integration factor automatically. Therefore, it is necessary to make this field editable to allow manual adjustments and ensure correct IMSS contributions. target: master task-6267003
Enhancements to existing features
The payroll pay run card now adapts to the actual space available inside the card, not just the browser window size. This makes the header, progress steps, KPI information, and action buttons behave more predictably on different screen sizes and reduces awkward wrapping or overflow.
Original PR description
The pay run header card was assembled by kanban XML inheritance and its responsive behaviour keyed off `ui.size` (the browser-window breakpoint). Regions shifted from one step to the next, and the…
The pay run header card was assembled by kanban XML inheritance and its responsive behaviour keyed off `ui.size` (the browser-window breakpoint). Regions shifted from one step to the next, and the free space and the buttons collapsed based on the window rather than the card's own width - folding while there was still room and overflowing when there wasn't. Rework it into a single OWL shell (PayrunCard) that owns four regions - name | KPIs | steps | buttons. Per-step views only fill the `payrun_kpis` slot and declare their `current_step`; the name block and step bubbles are declared once and reused. The kanban record owns one ResizeObserver that measures the card's actual width and each region's content width, then resolves the layout in priority order: the name truncates to its floor, the buttons collapse into the overflow menu, and finally the steps stack onto their own full-width row. The decision is recomputed only when the width changes, so toggling the layout - which only changes the height - cannot feed back and flicker at the boundary. task-6259171
Payroll administrators can now view and update the first payroll month directly in Payroll Settings. This makes it easier to correct or adjust the initial payroll setup after it has already been entered from the dashboard warning.
Original PR description
Currently, after set the first month of payroll on the dashboard warning. We can't modify it after nor the the information back. In this PR expected to add the first month of payroll in the Payroll Setting, Therefore, Users can modify after set it. task-6377702
Belgian payroll now handles youth and senior time off as separate categories, making payroll and leave tracking clearer. The update also adds checks to warn when youth time off seniority conditions may not be met and to prevent these allocations while regular paid time off remains available.
Original PR description
This PR: - Splits the youth and senior time off types into two different work entry types. - Adds a warning on the allocation of Youth Time Off if the employee does not have at least 1 month of seniority in the company at the beginning of the validity period for the allocation. - Prevents the allocation of youth or senior time offs if there is still paid time off available. task-6360468
Timesheet entry units are now controlled by timesheet settings instead of company-level settings. This makes time tracking behavior more consistent across related areas such as helpdesk, projects, sales timesheets, dashboards, and timesheet grids.
Original PR description
Adjust the `timesheet_encode_uom_id` to depend on timesheet settings, not from company --- # task cancelled task-5932762
The AI app form views and related controls were reorganized to make AI agents and their sources easier to manage. The update also adds native skills and lets agents update themselves, improving flexibility for businesses using AI workflows.
Recurring project tasks are now scheduled around assigned users’ workable days, working hours, leave, and contract dates. This helps teams plan recurring work more realistically while still allowing weekend-based recurrences when the original task was intentionally set on a weekend.
Original PR description
## Previous behavior: Recurrent tasks could still be scheduled on weekends, vacation days, or other non-working days. ## New expected behavior: Recurrent tasks are always scheduled based on the…
## Previous behavior: Recurrent tasks could still be scheduled on weekends, vacation days, or other non-working days. ## New expected behavior: Recurrent tasks are always scheduled based on the workable days and working hours of the users assigned to them. Workable days and hours are determined using the assigned users’ shared calendars. If the assigned users do not share the same calendar, the company calendar is used to resolve scheduling conflicts. If a user is on leave, the recurrent tasks they are assigned to are still scheduled, but the user is temporarily removed from the list of assigned users for the duration of their leave.This allows other individuals to take over the task when the user is on leave. Users are also removed from recurrent tasks when their contract start or end dates fall outside the task schedule since users shouldn't work with outdated contracts. ## Exception: This behavior can be overridden if the original recurrent task was initially scheduled on a weekend day (Saturday or Sunday). In this case, recurrent tasks behave exactly as before and may be scheduled on non-working days. This was made to ensure the end-users could have the final say on this behavior in the case it is unwanted. ## Reference: [task-4796700](https://www.odoo.com/odoo/project/4105/tasks/4796700)
Payroll warning settings can now show the same warning on both dashboards and employee or payroll record pages at the same time. This reduces duplicate setup work and makes important payroll alerts more consistently visible across supported country payroll modules.
Original PR description
Replace the `display_on` selection field with two distinct boolean fields: `display_on_dashboard` and `display_on_model`. This allows a single warning configuration to be displayed on both the dashboard and record views simultaneously, eliminating the need for data duplication. Update the view to show these choices as side-by-side checkboxes. Task: 6267499
Creating a shift from the Attendance Gantt view now uses the employee's expected daily working hours instead of defaulting to a full 24-hour shift. This prevents incorrect overnight shifts and avoids accidentally moving the end date to the next day.
Original PR description
Currently, when creating a new shift from the Gantt view in "Attendance", if the scale is "week" or higher, the shift will have a duration of 24 hours and span from 12:00 AM to 12:00 AM the next day. This will always be wrong, and also shifts the end date by a day. To resolve this issue, now if a new shift is created by clicking on a day (instead of dragging the click to select hours), editing the starting hour will automatically change the end hour to be start + expected hours per day. Task ID:6326685
Belgian payroll now supports restructuring social security reductions for up to three quarters instead of two. A new start date field helps track cases where an employee already received the reduction with a previous employer, improving payroll accuracy and compliance.
Original PR description
**What**: - Restructuring reduction can be received for 3 quarters previously it was only for 2 quarters - There is a chance that the person can get restructuring reduction from previous employer so added a new field 'restructuring_date_start' to know the start date of restructuring reduction task-6344925
The salary calculator now waits to show missing-field errors until users try to configure benefits or copy a link, instead of interrupting them while they are still editing. This makes the offer setup process smoother while still clearly listing required information before key actions can continue.
Original PR description
The salary calculator was showing validation errors while users were still filling in the form. This made the calculator harder to use. With this change: - Do not show validation errors while editing a simulation offer. - When the user clicks "Configure Benefits" or "Copy Link", validate all required fields and show an error listing any missing fields. - Remove the "Optional" placeholder from the employee field since it is required to use these actions. Task-6340556
Mexican payroll CFDI checks have been updated to match version 1.2e requirements. This helps ensure payslip XML data is validated correctly for taxable and exempt earnings, other salary income, and employment subsidy limits before reporting.
Original PR description
**. Perceptions – ImporteGravado / ImporteExento (XML Nodes)** For each Perception node, validate that: If ImporteExento = 0, then ImporteGravado > 0. If ImporteGravado = 0, then ImporteExento > 0. Both values cannot be 0 at the same time. These validations must be applied per Perception node, not at an aggregated level. **. TipoPercepcion = "038" (Other Salary Income) (XML Nodes)** When TipoPercepcion = "038": ImporteExento must always be 0. The amount must be recorded only in ImporteGravado. **. SubsidioCausado (XML Nodes)** Update the validation logic for the SubsidioCausado attribute based on NumDiasPagados: If NumDiasPagados ≤ 31, SubsidioCausado ≤ 628.00 If NumDiasPagados > 31, SubsidioCausado ≤ NumDiasPagados × 0.206 task-5412728 Forward-Port-Of: odoo/enterprise#121304
Hong Kong payroll salary rules have been consolidated so regular and casual employee structures can share common rules instead of maintaining duplicate versions. This reduces configuration complexity and should make payroll support and future updates easier while preserving the differences needed for MPF rules.
Original PR description
Recently, salary rules were updated to support more than one salary structure on a same rule. This change allows us to clean our structures and remove a lot of duplication between regular and casual employees. Both structures are 90% the same, besides MPF rules, so we now can really simplify it to facilitate support and reduce complexity task-6267295
Belgian payroll rules now reflect the legal change effective August 1, 2026: employees with less than six months of service have a one-week notice period whether they resign or are dismissed. This helps employers calculate end-of-collaboration notice durations correctly and consistently, including contracts that span the change date.
Original PR description
Starting from August 01 2026, the legal notice period will change if the employee has been working for their company less than six months: it will only be one week, no matter if the employee quit or was fired. Task: 6365099
Payment check reports now better explain cases where a check is written for less than the invoice total because an early payment discount was applied. This helps users and recipients understand the payment amount and keeps localized payment report layouts aligned.
Original PR description
Previously, the check amount didn't match the applied payment. This makes it clear why the a check for less than the total was written out. Because we change the layout of the payment report in community, we have to update some xpaths here. For MX, a `is_cfdi_signed` block was not migrated because it's dead code. That variable isn't defined anywhere. task-5172527
Resolved issues and error corrections
This change restores payroll fields that were removed too early, including the refund indicator and beneficiary details for salary attachments. It helps ensure payroll payments and related reports can continue handling beneficiary information while the longer-term design is reconsidered.
Original PR description
In this previous PR (https://github.com/odoo/enterprise/pull/114188) we removed the is_refund flag and, together with it, also the fields related to the beneficiary. This is because there is an onchange method on is_refund that sets the beneficiary bank account for any attachment that is not a refund to False. However, while the removal of is_refund is still in the plans, we want to take back the beneficiary fields and use them even in the case of non-refund attachments. We need to think better about how to remove the is_refund field and structure negative attachments around it, so for now we revert the previous PR. Task: 6376383 Forward-Port-Of: odoo/enterprise#123728
Instagram image posts that hit network delays will now be marked as failed instead of causing a server crash. Users receive clearer failure messages, including guidance to use a smaller image when timeouts occur.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#122406 Forward-Port-Of: odoo/enterprise#112573
This fixes an installation blocker for the Peruvian electronic invoicing localization caused by a typo in an internal database query. Businesses using or enabling Peru localization can install the module successfully again.
Original PR description
A refactor/cleanup [1] introduced a buggy SQL query preventing the Peruvian localization install. [1]: https://github.com/odoo/enterprise/commit/e182608f13c6eefae11339bba24e80497c2b3903#diff-deaab3f5010fea8defc8af11dc186415ecc9079d86d307537b09222dda7ab751R119 task-none
This update fixes issues in the social CRM and social feed experience where post menus could appear empty, feed refreshes could fail due to timeouts, and LinkedIn image uploads could error. The changes make day-to-day social media management more reliable and reduce interruptions for users working with social posts and leads.
Original PR description
Bug 1 === Since b75755ea8ac65ce5ce973412e3c4194fa1bd6fd3 , the menu on the stream post could be visible but empty. The reason is that we checked for `this.isConvertibleToLead` instead of `this.isConvertibleToLead()`. We take advantage of this bug fix to correctly overwrite the condition without replacing the entire button (which can break other module overwriting the same element). Bug 2 === Sometimes, when refreshing the feed view, an error occurs because the request timeout. To fix it, we increase the timeout when doing requests in batch. Bug 3 === When uploading an image in LinkedIn, an error happens. The reason is that `LocalBinaryFile` is now returned when reading Binary field, and in the requests API, the `data` arguments expect the bytes. (for other media, we upload the image with `file` argument). Task-6254983 Forward-Port-Of: odoo/enterprise#123949 Forward-Port-Of: odoo/enterprise#118329
Subscription product pages now load correctly when a discount is configured directly on a recurring plan without a pricelist. This prevents website errors during price calculation and ensures customers see the intended discounted recurring price.
Original PR description
**Problem:** On the website, a subscription product page returns a 500 error when a discount is set directly on the recurring plan (a time-based pricing rule with a plan but no pricelist). **Steps to…
**Problem:** On the website, a subscription product page returns a 500 error when a discount is set directly on the recurring plan (a time-based pricing rule with a plan but no pricelist). **Steps to reproduce:** 1. Create a subscription product with a recurring plan. 2. Add a recurring price rule for that plan with no pricelist, set as a percentage discount (base = sales price). 3. Open the product page on the website. **Current behavior:** The page fails with a 500: Internal Server Error during price computation. **Expected behavior:** The page loads and shows the discounted recurring price. **Cause of the issue:** For a recurring price rule based on the sales price, `_compute_base_price` looks up "the no-pricelist rule for the plan" to use as its base, via `_get_applicable_rules_domain(plan_id=...)`. When the discount is set directly on the plan, the rule being computed has no pricelist itself, so that search returns the very same rule and calls `_compute_price` on it again, leading to infinite recursion. **Fix:** Excluding the rule itself from the base-rule lookup lets a no-pricelist plan rule resolve its base from the product's sales price (the super() fallback) instead of re-entering its own computation. A rule applied through a pricelist is unaffected, since its no-pricelist base rule is a different record. opw-6306105 Forward-Port-Of: odoo/enterprise#121466
Fixed a conflict that caused Obox quality-control cameras to stop working after the IoT module was installed. Users can continue taking required quality-check photos without seeing a false camera-not-found error, and irrelevant IoT controls are hidden when no IoT device is configured.
Original PR description
Steps to reproduce: - Install `obox_quality_control` but do not install `iot`. - Configure a quality check to take a picture with an Obox camera. - Validate a receipt an confirm the camera works as expected. - Now install the `iot` module, and try to take a picture again. **Expected behaviour:** The camera still works as expected. **Actual behaviour:** There is a 'Camera not found' error. This issue is caused by both the Obox and IoT quality modules adding an `identifier` field to the quality control wizard. The fix is simply to use a different name for the Obox field. In addition, we now hide the IoT button in the wizard if the IoT device is not set. task-6329066 Forward-Port-Of: odoo/enterprise#122490
Fixes an installation and upgrade failure in the Peru electronic invoicing module that could affect databases with existing journal entries. This helps ensure updates complete successfully and required invoice data is filled in correctly.
Original PR description
### Description Installing or upgrading `l10n_pe_edi` aborts with a `psycopg2.errors.SyntaxError` whenever `account_move` already contains rows: ``` psycopg2.errors.SyntaxError: syntax error at or…
### Description
Installing or upgrading `l10n_pe_edi` aborts with a `psycopg2.errors.SyntaxError` whenever `account_move` already contains rows:
```
psycopg2.errors.SyntaxError: syntax error at or near "AND"
LINE 9: AND l10n_pe_edi_operation_type IS NULL
```
### Root cause
The `init_storage` SQL that backfills `l10n_pe_edi_operation_type` (added in e182608f13c6 `[REF] *: use init_storage`) closes the `WHERE` clause with a stray semicolon right after the country condition:
```sql
WHERE res_company.id = account_move.company_id
AND move_type IN ('out_invoice', 'out_refund')
AND res_country.code = 'PE'; -- stray ';' ends the UPDATE
AND l10n_pe_edi_operation_type IS NULL -- parsed as a new statement -> syntax error
```
The semicolon terminates the `UPDATE` early, so `AND l10n_pe_edi_operation_type IS NULL` is parsed as a separate statement starting with `AND`.
`init_storage` only runs when the table already has rows (`_init_column_data` in `odoo/orm/fields.py` skips empty tables), which is why the crash surfaces on databases that already contain journal entries — e.g. runbot `*-all` builds, or `button_immediate_install` over a populated database.
### Fix
Remove the stray semicolon so the NULL guard stays part of the `WHERE` clause.
### Validation
Reproduced and verified on `master` (community + enterprise), with a row present in `account_move`:
- **Before:** `-u l10n_pe_edi` fails with `syntax error at or near "AND"` at `LINE 9`.
- **After:** the module installs/updates cleanly and the column is backfilled without error.Twitter replies are now blocked in Odoo when the account is not allowed to respond, such as when the tweet does not mention the account or quote one of its tweets. This prevents failed or inappropriate automated replies and helps avoid unwanted outreach to Twitter users.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524
Canadian EFT batch payment exports now use each payment's ID as the Item Trace Number instead of filling it with zeros. This helps ensure files comply with CPA-005 banking rules and avoids payment rejections by Canadian financial institutions.
Original PR description
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as…
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as a zero-filled sequence According to CPA-005 standards on the Item Trace Number: "The data elements (b), (c) and (d) each must be greater than zero or the TRANSACTION WILL BE REJECTED" (page 36). https://www.payments.ca/sites/default/files/standard005eng.pdf Steps to reproduce: 1. Install the module l10n_ca_payment_cpa005 2. Go into "CA Company" 3. In the configuration for "CA Company", add something to the fields "Short Name used in Canadian EFT" and "Company ID" i.e. "CCC" 4. Set all the fields in the "Canadian EFT/CPA Configuration" section of the bank journal 5. Set the bank record on the bank journal. Set the field "Financial Institution ID Number" field of the "Account Number" record of the bank journal to any numerical sequence 6. Create a bank account on "Azure Interior" and make sure to check the field to trust the bank account that you created (otherwise there will be an error) 7. Create two payments with the vendor of "Azure Interior" using the payment method of "Canadian EFT" 8. Create a batch payment for both payments created 9. Validate the batch payment and the export file should show up in the chatter 10. Note that in the export file, the Item Trace Number for each payment is set to be all zeros, whereas it should be a nonzero identification sequence Solution: Set the Item Trace Number to be the payment's id opw-6323432 Forward-Port-Of: odoo/enterprise#124016 Forward-Port-Of: odoo/enterprise#123633
The timesheet assistant now captures time spent in Odoo applications even when the activity cannot be linked to a specific project, task, or ticket. This helps users get more complete time suggestions, with these activities shown as separate key entries for easier review.
Original PR description
This PR adds support for tracking time spent in the Odoo apps in the assistant, for when we can't trace URLs to a project/task/ticket. The activities detected this way are marked as key events, such that each appears as an individual line in the assistant suggestions. With this, most of the time users spend working in their Odoo database should be reflected in the assistant suggestions. Task-6250449 Forward-Port-Of: odoo/enterprise#123147 Forward-Port-Of: odoo/enterprise#119096
This update improves manufacturing work order planning by showing planned work orders by default and aligning shop floor card options with company settings. It also corrects engineering change cost calculations so bill of materials cost differences better reflect real operation cost changes.
Original PR description
Forward-Port-Of: odoo/enterprise#122639
Fixes an issue where the cursor could jump backwards while users typed in Studio's XML editor. The editor now keeps cursor position reliably per editing session, making report and view editing smoother and less disruptive.
Original PR description
Steps to reproduce the issue: -> Open studio -> Edit any view -> Edit xml => Cursor moves backwards when typing Some components inside of the report editor were managing the cursor position based on the document manually. Rendering timings could cause the cursor to move while typing. This commit internalizes the cursor position in the CodeEditor and keep track of them based on the sessionsId, making sure that the cursor position is always correct and only changing when switching between sessions while also making the component API simpler. Community: https://github.com/odoo/odoo/pull/274681 Forward-Port-Of: odoo/enterprise#123244
Employees and managers can now request and save appraisals even when the scheduled appraisal date has already passed. This removes an unnecessary error that blocked late appraisal requests and avoids requiring users to manually adjust dates they may not have permission to change.
Original PR description
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings,…
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings, set Next Appraisal Date to tomorrow and wait for 2 days Then : - Click on Request Appraisal - Save # The problem An error is shown saying "You cannot set 'Next Appraisal Date' in the past.". You can workaround this by changing the Next Appraisal Date to a date in the future, but the problem is not every user has the right to do this. # Cause `next_appraisal_date` is also defined in hr.appraisal as a relate field of hr.employee : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_appraisal.py#L56-L57 When creating an hr.appraisal, `next_appraisal_date` is present in `vals_list` because it is defined in the view since : https://github.com/odoo/enterprise/commit/58fba3098f33db82dfbccca2db229550402ed3ab https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/views/hr_appraisal_views.xml#L92 This triggers a write on `next_appraisal_date` of hr.employee which triggers a constraint : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_employee.py#L81-L85 opw-6147865 Forward-Port-Of: odoo/enterprise#123817 Forward-Port-Of: odoo/enterprise#114876
Rental planning now only blocks resources for company-wide leave when that leave applies to their working calendar, preventing unnecessary allocation conflicts. The update also strengthens related rental planning website and backend tests to help keep booking behavior reliable.
Original PR description
## [FIX] sale_renting_planning: check global leaves working schedule Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated…
## [FIX] sale_renting_planning: check global leaves working schedule
Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated during the leave date.
After this commit: any `resource.calendar.leaves` with `no resource_id` would be applied only to resources with the same `calendar_id` as the leave.
if the leave has no `calendar_id` then the leave applies to all `resource.calendars`
if a resource has no `calendar_id` then leaves with no `calendar_id` apply to it as well
## [IMP] {website_}sale_renting_planning: move tests from industry and fix existing ones
This commit moves the tests from [odoo/industry#1980](vscode-file://vscode-app/snap/code/237/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) to their respective standard modules.
It also fixes the logic behind some tests as they weren't testing a `planning.role` with `sync_shift_rental` enabled.
task-6179505
Forward-Port-Of: odoo/enterprise#120983
Forward-Port-Of: odoo/enterprise#116430Belgian payroll pay runs no longer fail when an employee has multiple contract or work schedule versions within the same month. This ensures payslips can be generated reliably for employees with mid-month changes, reducing payroll processing interruptions.
Original PR description
Currently, there is an error while running payrun step with employee who has multiple version in 1 month. ``` number_of_hours = (work100_wds - worked_day).number_of_hours ValueError: Expected singleton: hr.payslip.worked_days(233, 234) ``` Step to reproduce: 1. Create Employee with multiple version in 1 month 2. Create New PayRun during that month 3. Run the PayRun until Payslip step 4. Expected error on payslip steps reason: substraction of work100_wds and worked_day generate more than 1 value, if we have multiple version in 1 month task-6296276 Forward-Port-Of: odoo/enterprise#122723 Forward-Port-Of: odoo/enterprise#122483
This update fixes several issues around how taxes are calculated and stored when documents switch tax modes. It improves consistency for invoices, purchases, sales, and Italian electronic invoice imports, reducing the risk of incorrect totals or validation issues.
Original PR description
- changing python constraint on document tax mode on account.move to SQL - style enhancements to the overlap_badge_tab and new component - removing inconsistent rounding in purchase.order - adding document tax mode logic to account.tax compute_all method - adding missing document tax mode ‘tax_excluded’ setting to l10n_it_edi during account.move creation of imported invoices odoo/odoo/pull/272730 Following up: https://github.com/odoo/odoo/pull/251800 Forward-Port-Of: odoo/enterprise#122246
Features or functions removed from Odoo
Belgian payroll calculations are updated so employees in Brussels no longer receive the elderly worker reduction starting in Q3 2026. This keeps payroll results aligned with the regional rule change and updates validation tests accordingly.
Original PR description
removed the reduction for everyone in BXL starting Q3 2026 and adapted the tests task - 6331080 Forward-Port-Of: odoo/enterprise#123921
7 changes
Enhancements to existing features
The Mexican payroll localization now includes the latest SAT perception and deduction concepts in the payroll CFDI catalog. This helps businesses keep payroll reporting aligned with current Mexican tax authority requirements.
Original PR description
Adds the new SAT perception and deduction concepts to the Mexican payroll CFDI concept catalog. task-6295124
The French balance sheet now presents establishment costs before fixed assets, matching the expected reporting structure. It also includes previously missing impairment accounts for tangible fixed assets, improving the completeness and accuracy of financial statements.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138
Resolved issues and error corrections
Fixed an issue where attendee emails could show an outdated event start date after a multi-day event was rescheduled. This ensures participants receive accurate event timing information when organizers update event dates.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date` to recompute value on changing the date of the event opw-6284576 Forward-Port-Of: odoo/enterprise#120184
Mexican payroll payslip forms no longer crash when users add daily salary or integration factor fields with Odoo Studio. This lets payroll teams safely review salary calculation inputs, including while creating off-cycle payslips before an employee is selected.
Original PR description
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule…
Users frequently use Odoo Studio to display the Daily Salary (`l10n_mx_daily_salary`) and Integration Factor (`l10n_mx_integration_factor`) fields on the payslip form to verify salary rule computations. However, doing so raises a traceback immediately upon closing the Studio editor, as well as when attempting to create a new Off-Cycle payslip.
### Steps to reproduce:
* Install `l10n_mx_hr_payroll` and `web_studio`.
* Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company.
* Go to Payroll > Payslips > Payslips and create a "New Off-Cycle"
* Use the Studio editor to add `l10n_mx_daily_salary` or `l10n_mx_integration_factor` fields.
* Close the Studio editor.
### Current behavior:
A traceback is raised depending on the field added
#### For the Daily Salary field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 21, in _compute_daily_salary
payslip.l10n_mx_daily_salary = payslip.version_id.wage / payslip._rule_parameter('l10n_mx_schedule_table')[payslip.version_id.schedule_pay]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: False
```
#### For the Integration Factor field:
```py
File "/Users/ivgm/odev/worktrees/19.0/enterprise/l10n_mx_hr_payroll/models/hr_payslip.py", line 33, in _compute_integration_factor
payslip.employee_id.with_context(before_date=payslip.date_from)._get_first_contract_date()
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 493, in _get_first_contract_date
versions = self._get_first_versions_filtered(no_gap=no_gap).filtered(lambda x: x.contract_date_start)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ivgm/odev/worktrees/19.0/odoo/addons/hr/models/hr_employee.py", line 461, in _get_first_versions_filtered
self.ensure_one()
File "/Users/ivgm/odev/worktrees/19.0/odoo/odoo/orm/models.py", line 5942, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: hr.employee()
```
### Expected behavior:
No error is raised, and the fields are correctly displayed on the form view.
### Solution:
* Add Guard Clause: When creating a "New Off-Cycle" payslip, `payslip.version_id` is not initially set because no employee has been selected yet. Added a condition to check if `version_id` exists before computing the values to prevent the traceback.
* View Update: Since displaying these fields is a highly requested feature for traceability, they have now been added to the form view.
target: 19.0
task-6267003Opening transfers in the barcode app now applies a default limit when loading reusable packages. This prevents very large package lists from causing long waits, improving usability for warehouses with high package volumes.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730
Bank reconciliation now correctly shows exchange rate adjustment entries again. This helps accounting teams review and match foreign-currency transactions accurately without missing related exchange movements.
Original PR description
Fix a bug where the exchange moves are no more displayed in the bank reco widget. Bug introduced here: https://github.com/odoo/enterprise/pull/119557 no-task
Kitchen preparation orders now keep their place when staff mark individual order lines, avoiding confusing reordering after a page reload. Orders only move to the back when they actually change preparation stage, making the display more predictable for restaurant teams.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046
8 changes
Resolved issues and error corrections
This fix prevents an accounting dashboard filter from accidentally interfering with Mexican CFDI payment document updates. Users can now update payments without encountering an unexpected error when documents integration is enabled.
Original PR description
Issue: The `default_type` context can leak into documents creation with invalid values (e.g., 'sale' for documents.document.type), causing a ValueError. Steps to reproduce: - Use a Mexican company with CFDI credentials configured. - Install the documents_account module and create a folder for journals where you will place customer payments. - Create an invoice with "payment policy = PPD", and send it to CFDI. - Create a bank transaction and reconcile it with the invoice. - Go to the Accounting Dashboard, remove current filters, and group by "Type" (this injects default_type into the context). - From there, enter the "Sales" journal and open the invoice. - Click on the "Update Payments" button. - Result: `ValueError: Wrong value for documents.document.type: 'sale'` Fix: Clean context from the `default_*` keys when creating the attachment of the document. opw-6141172
Colombian electronic invoice imports now keep the XML unit price as provided by DIAN instead of dividing it by the quantity. This prevents incorrect negative discounts from appearing on vendor bills when imported items have quantities greater than one.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. task-6215466
This fixes an issue where partial receipts involving subcontracted products could incorrectly mark related items as processed, causing backorders to be created with the wrong quantities. Businesses receiving mixed subcontracted and regular products through barcode workflows should now get more accurate receipt validation and backorder handling.
Original PR description
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units -…
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units - Validate the receipt and create a backorder #### > Only the subcontracted move has been kept on the receipt and a backorder was created for 3 units of P1 and 5 of P2. ### Cause of the issue: Setting the quantity of the subcontracted move will automatically record the quantities on the subcontracted MO: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L83 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L123 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L91 However, the `_update_finished_move` method adds and update the related subcontracted move lines marking them as *picked* to adapt the related reservation: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L118-L164 This is problematic since picking a move line will also pick the move: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/stock/models/stock_move.py#L261-L267 And only picked moves are considered to be processed at picking validation. ### Note: The exact same issue had already been fixed in 17.0: db8b33ebb9fe23507bcba30b12741e4d688ae549 However, the fix had an issue concerning the barcode behavior as it removed the picked computation for subcontracted moves which made hybrid pickings such as the above one (with one subcontracted and one non-subcontracted move) impossible to process in the barcode app. As such, the fix and test where reverted in cf2d18c92bee55ef79db1a338e9baf12f258ee5b The present commit provides an alternative fix of the original issue keeping subcontracted moves unpicked by quantity changes without affecting the picked computation of subcontracted moves (e.g. adding a picked move line on a subcontracted move will still pick that move). Community: https://github.com/odoo/odoo/pull/275304 opw-6330584
Fixes an issue where General Ledger spreadsheet exports for a single selected journal showed tax declaration lines multiple times, breaking the report layout. The export now includes those tax lines only once and limits account processing to the selected journal, producing a clearer and correctly formatted file.
Original PR description
## Issue When exporting the General Ledger in xlsx format with only one journal selected, the tax declaration lines appear multiple times and are disrupt the overall format of the report. ## Steps to…
## Issue When exporting the General Ledger in xlsx format with only one journal selected, the tax declaration lines appear multiple times and are disrupt the overall format of the report. ## Steps to reproduce 1. Install *Accounting* (`account_accountant`) with demo data 2. In Accounting > Reporting > General Ledger, select a single journal (e.g. Customer Invoices) and click the *XLSX* export button. 3. **The resulting XLSX file is incorreclty formated. The tax declaration lines appear multiple times and disrupt the structure of the report.** <img width="1012" height="603" alt="image" src="https://github.com/user-attachments/assets/1d22e9a1-3fc2-4538-b1bd-4ca1d1bbe092" /> ## Cause Since https://github.com/odoo/enterprise/commit/6a3804c5fe6b4f1d48a4ab311a0f1fbb24d75187, the xlsx report is generated by iterating over the relevant accounts and injecting the lines into the report account by account. https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_general_ledger.py#L773-L775 The [`_get_accounts_with_move_lines` method](https://github.com/odoo/enterprise/blob/17.0/account_reports/models/account_general_ledger.py#L814) does not take into account the journals that are requested when exporting .xlxs, which leads to too many accounts being iterated over. Before that commit, the `_get_lines` method was only called once when generating the xlsx report. This explains the behaviors below, that were not properly adapted to call the method multiple times to generate a single report. The first issue is that the `_get_lines` method calls the `_dynamic_lines_generator` method, which adds the tax declaration lines after each account when only one journal is selected: https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_general_ledger.py#L88-L91 To avoid that, we can add a context key to prevent the injection of the tax declaration lines for all iterations, then add the lines afterwards. Another issue is that the accounts chosen to iterate over do not take the selected journal into account. Without doing so, we iterate over too many accounts, which is inefficient, but which also adds the tax declaration lines (and only those lines) for those irrelevant accounts. That is why the tax declaration lines appear multiple times in the incorrect reports: they were added for accounts that were not supposed to belong in the report. Lastly, because the total line is added individually, it would not be bold because of the following condition from `inject_lines_into_xlsx_sheeŧ`: https://github.com/odoo/enterprise/blob/b6d27f428e2b966e38b65e820e1454b711483996/account_reports/models/account_report.py#L5262-L5266 ## Performance Impact Because the commit introducing the issue (https://github.com/odoo/enterprise/commit/6a3804c5fe6b4f1d48a4ab311a0f1fbb24d75187) is a [PERF] commit, the performance impact of this fix was evaluated. The table below shows the time taken to export the XLSX report of the General Ledger for a various amounts of `account.move.line`. Each value represents the average execution time over 10 runs (in milliseconds), with the standard deviation shown in parentheses. | | Before (ms) | After (ms) | |--------|------------------|------------------| | 100 | 321.25 (± 49.56) | 363.43 (± 59.93) | | 5,000 | 1759 (± 71.87) | 1773 (± 60.19) | | 10,000 | 2723 (± 70.72) | 2765 (± 106.8) | | 50,000 | 11501 (± 170.32) | 11567 (± 165.87) | opw-5783588 Forward-Port-Of: odoo/enterprise#111826
French VAT declaration submissions now handle SIRET numbers even when users enter spaces, preventing avoidable filing failures. The update also checks bank account number formatting and warns users before submission if something looks incorrect.
Original PR description
This commit resolves an issue where VAT declarations failed when the provided SIRET number included spaces. Since check_siret verifies the format, we now strip all spaces from the input. Additionally, this commit introduces a validation for bank account numbers, ensuring that we warn the user if the account number is wrongly formatted. task-6253745
Fixes an issue where Uruguay e-Ticket Credit Notes linked to original e-Tickets totaling 0.00 could be rejected by the tax authority because a required reference amount was omitted. The required zero amount is now included, helping businesses submit compliant credit notes without manual intervention.
Original PR description
Problem: When generating an e-Ticket Credit Note for an original e-Ticket with a total amount of 0.00, the XML cleanup mechanism removes reference fields whose value is 0.00. As a result, the credit note is rejected by DGI with: "CODE 31: En línea de Referencia 1 si NO IndGlobal = 1 deben existir TpoDocRef, Serie, NroCFERef, MntCFERef, TpoMonedaRef." Solution: Ensure that MntCFERef is sent even if the value is 0.00. opw-6378783 Forward-Port-Of: odoo/enterprise#124354
Invoices marked as 'No Follow-Up' are now properly left out of follow-up email attachments and printed follow-up letters. This prevents customers from receiving statements that include invoices the business intentionally excluded from follow-up actions.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602
This update fixes an issue where vendor bills generated from Colombian XML imports incorrectly applied discounts due to a misinterpretation of price unit calculations. The change ensures that the PriceAmount is correctly parsed as the unit price, aligning with DIAN regulations and preventing negative discounts on invoices.
Original PR description
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price…
Problem: When importing XML files to generate vendor bills, the system uses UBL parser and assumes that the PriceAmount node needs to be divided by the BaseQuantity node to obtain the exact price unit. However, in Colombia, the DIAN treats the PriceAmount node as the exact price unit. This was not flagged in the system so the parser incorrectly divides the PriceAmount by BaseQuantity, resulting in negative discounts to be added to match the subtotal. Solution: Extract the basis_qty logic into a helper method so other localizations can override when needed. Current behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets incorrectly divided, resulting in negative discounts on the vendor bill. Expected Behavior: When importing a Colombian XML with a product that has a BaseQuantity greater than 1, the PriceAmount gets parses as the exact unit price with no negative discounts applied. Task [link](https://www.odoo.com/odoo/project.task/6215466) task-6215466
1 change
Resolved issues and error corrections
Subscriptions that include zero-price recurring products now correctly show delivered quantities as invoiced after an invoice is confirmed. This prevents subscriptions from incorrectly remaining marked as still to invoice, giving users a more accurate billing status.
Original PR description
Steps to reproduce: ---------------------------------------------- 1. Install Subscription module 2. Create two recurring products with the following configuration: * Type: Service * Invoicing…
Steps to reproduce:
----------------------------------------------
1. Install Subscription module
2. Create two recurring products with the following configuration:
* Type: Service
* Invoicing Policy: Delivered Quantities
* Set the Sales Price of one product to 0.0
3. Create and Confirm the Subscription having both products
4. Set a delivered quantity on both subscription lines
5. Create and confirm an invoice for the subscription
6. Check the Invoice status in the Other Info tab (Enable Debug mode)
Observation:
----------------------------------------------
1. Invoiced Quantity remains 0 for both products
2. Invoice status remains 'To Invoice' instead of 'Fully Invoiced'
Issue:
------------------------------------------------
`_compute_qty_invoiced` internally reads `order_id.next_invoice_date` (via `_get_subscription_qty_invoiced`) to determine the billing period window used to match invoice lines.
https://github.com/odoo/enterprise/blob/21c93f40f3367d3be77d2e78fdee1b7cb6449978/sale_subscription/models/sale_order_line.py#L176-L179 The problem is a timing issue during `_post()`.
1. `sale_subscription._post()` calls `super()._post()` which goes to `_generate_deferred_entries()`
2. For zero-price lines, all deferral moves have `amount_total = 0`, so they get unlinked
https://github.com/odoo/enterprise/blob/21c93f40f3367d3be77d2e78fdee1b7cb6449978/account_accountant/models/account_move.py#L304-L305
3. This unlink triggers an ORM flush which forces `_compute_qty_invoiced` to run NOW, but `next_invoice_date` hasn't been updated yet (it's still the start date)
4. With the stale `next_invoice_date`, the period window is wrong, so no invoice lines match → `qty_invoiced = 0`
5. Control returns to `sale_subscription._post()` which then updates `next_invoice_date` to the correct value, But `_compute_qty_invoiced` is never re-triggered because `next_invoice_date` is not in its `@api.depends`
Additionally, `_compute_invoice_status` unconditionally forces `invoice_status = 'no'` for any line with `price_subtotal == 0`, even after that line has been fully invoiced and delivered.
https://github.com/odoo/enterprise/blob/21c93f40f3367d3be77d2e78fdee1b7cb6449978/sale_subscription/models/sale_order_line.py#L63-L64
Solution:
------------------------------------------------
1. In `_post()`, after updating `next_invoice_date`, explicitly mark `qty_invoiced` for recomputation on recurring lines. This ensures it is recomputed with the correct `next_invoice_date` value
2. In `_compute_invoice_status`, add `and line.invoice_status != 'invoiced'` to the zero-price check so that once a zero-price line is fully invoiced (as determined by `super()`), it retains the 'invoiced' status instead of being overridden to 'no'.
Note:
----------------------------------------------
We cannot add `order_id.next_invoice_date` to the `@api.depends` of `_compute_qty_invoiced` because that would cause manual changes to `next_invoice_date` by users to incorrectly reset `qty_invoiced` to 0 (shifting the period window so existing invoice lines no longer match). This was the exact issue fixed by a prior commit that intentionally removed it from the dependencies.
https://github.com/odoo/enterprise/pull/65203/changes/e126a4008ef164b056b75031f2ec08aeb2bedd14
opw-5941955