Daily updates from Odoo
Wednesday, July 15, 2026
273 changes
8 changes
Resolved 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
The AI chat view now waits until the conversation has finished loading before showing the start message. This prevents users from briefly seeing an empty conversation screen and makes AI chats feel consistent with regular Discuss channels.
Original PR description
Only display the AI thread start message once the thread has finished loading, matching the behavior of regular Discuss channels and preventing a brief flash of the empty conversation. Update the AI-specific `showStartMessage` implementation to respect the base Thread loading state instead of always displaying the start message for AI channels. Community PR : https://github.com/odoo/odoo/pull/273991 task-6352578 Forward-Port-Of: odoo/enterprise#122808
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
Signature certificates now show the applicant’s real email address when an offer is generated and signed from Recruitment. This avoids misleading placeholder emails on certificate logs and keeps signed document records accurate.
Original PR description
similar to https://github.com/odoo/enterprise/pull/120566/changes/b5b6589c9c91980e41d025ae74082af63907debc When generating an offer from the recruitment application and signing it, the applicant's…
similar to https://github.com/odoo/enterprise/pull/120566/changes/b5b6589c9c91980e41d025ae74082af63907debc When generating an offer from the recruitment application and signing it, the applicant's email address is incorrectly displayed. ### **Steps to Reproduce:** 1) Install sign, recruitment, hr_contract_salary 2) Create an new application and add basic detail like name and email as (path and path@test.com) 3) Generate offer and sign with all the required signer. 4) Open the application form view and open the certificate. ### **Observed Behavior:** Email is not set correctly in the generated certificate (appearing as john@example.com). ### **Expected Behavior:** The email of the applicant should be correctly set(e.g as path@test.com) ### **Root Cause:** When the applicant signs the document, their email is explicitly set to `False` at [1]. This is done because the applicant is not linked to any user yet. Later, when generating the certificate, the system attempts to display the user's partner email at [2], which is `False`, causing the default fallback value (`john@example.com`) to be printed. [1]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/hr_contract_salary/controllers/main.py#L53-L54 [2]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/sign/report/sign_log_reports.xml#L59 ### **Fix:** Use `signer_email` instead of the partner's email to ensure the correct email is displayed on the certificate every time. **opw-6280170** Forward-Port-Of: odoo/enterprise#124215 Forward-Port-Of: odoo/enterprise#123767
This update removes a reference to a staff access group that does not exist in the Belgian payroll fleet module. It prevents configuration errors and helps the related employee vehicle payroll fields work reliably.
Original PR description
The group hr_group_user does not exist and shouldn't be linked to these fields. task-6369268 Forward-Port-Of: odoo/enterprise#123238
New planning slots now use the company’s working hours in the company’s own time zone. This prevents default shift times from appearing offset, so users see the expected start and end times when scheduling resources.
Original PR description
Issue: ---------------------------------------- When creating a new slot, no resrouces are set so we use the calendar of the company but the hours are offset because of the timezone. Steps to reproduce: ---------------------------------------- - Have planning Installed - Have an hour based calendar, from 8 to 16 each day for example - Have the company timezone in UTC+2, same for you the user - Go in Planning "Schedule By Resource" view - Click "New" - The default start and end time are 10am and 6pm (2h offset) Cause: ---------------------------------------- `default_get()` calls `_company_working_hours()` to get the company calendar hours. But they are returned in UTC, so when displaying them they are converted to the user timezone and are offsetted. Solution: ---------------------------------------- `_company_working_hours()` should return the compny hours in the company timezone. opw-6333993 Forward-Port-Of: odoo/enterprise#123033
This fixes an issue where POS Pricer item update requests could receive data in the wrong structure after a previous update. It helps ensure price item updates are sent correctly, reducing the risk of failed or inconsistent pricing updates.
Original PR description
odoo/enterprise#120226 FW port introduced an inconsistency in the data passed to the items update request. This commit fixes it. Forward-Port-Of: odoo/enterprise#124282
Closing an empty AI chat after typing no longer triggers an error in the background. This avoids a disruptive traceback and makes the AI chat experience smoother for users who start and then close a conversation.
Original PR description
Typing in an empty AI chat calls notify_typing(true). Closing that chat unlinks the channel, then the composer’s onWillDestroy calls notify_typing(false) against a channel that no longer exists → NotFound traceback. so now we are stopping notify_typing only for of Ai chat deletion process. origin commit: https://github.com/odoo/enterprise/commit/03f7dcc01b5c816394b215c9253b0756f848211e task-6385788
18 changes
Resolved issues and error corrections
This fix prevents an error when opening Dimona data for an employee whose private street address is missing. It helps Belgian payroll users continue their workflow instead of being blocked by a technical traceback.
Original PR description
action_open_dimona guards on `self.employee_id.private_street` but then runs re.findall on `self.private_street` Forward-Port-Of: odoo/enterprise#124029
Signature certificates now show the applicant's actual email address when an offer is generated and signed from Recruitment. This avoids confusing placeholder emails on official signing records and keeps certificate logs accurate for HR processes.
Original PR description
similar to https://github.com/odoo/enterprise/pull/120566/changes/b5b6589c9c91980e41d025ae74082af63907debc When generating an offer from the recruitment application and signing it, the applicant's…
similar to https://github.com/odoo/enterprise/pull/120566/changes/b5b6589c9c91980e41d025ae74082af63907debc When generating an offer from the recruitment application and signing it, the applicant's email address is incorrectly displayed. ### **Steps to Reproduce:** 1) Install sign, recruitment, hr_contract_salary 2) Create an new application and add basic detail like name and email as (path and path@test.com) 3) Generate offer and sign with all the required signer. 4) Open the application form view and open the certificate. ### **Observed Behavior:** Email is not set correctly in the generated certificate (appearing as john@example.com). ### **Expected Behavior:** The email of the applicant should be correctly set(e.g as path@test.com) ### **Root Cause:** When the applicant signs the document, their email is explicitly set to `False` at [1]. This is done because the applicant is not linked to any user yet. Later, when generating the certificate, the system attempts to display the user's partner email at [2], which is `False`, causing the default fallback value (`john@example.com`) to be printed. [1]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/hr_contract_salary/controllers/main.py#L53-L54 [2]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/sign/report/sign_log_reports.xml#L59 ### **Fix:** Use `signer_email` instead of the partner's email to ensure the correct email is displayed on the certificate every time. **opw-6280170** Forward-Port-Of: odoo/enterprise#124215 Forward-Port-Of: odoo/enterprise#123767
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#121718The French reports module now formats the fiscal year end date consistently in the required month-day format. This prevents invalid report values when the fiscal year end month has only one digit, helping ensure compliant submissions.
Original PR description
Aspone force the end fiscal year in zone AD to follow the format MMdd. Before this commit, fiscalyear_last_month could be only one number and so we would end up with something like '930'. We will now add :02d to format the integer with a width of 2. task-6253745
Shopee order lines now show the specific variant SKU in the description instead of the broader template SKU when products have variants. This makes order details clearer for teams handling fulfillment, customer service, and sales reconciliation.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
Belgian payroll contract templates now correctly carry over three previously missing fields when creating contract versions. Simulation versions are also kept from triggering Dimona-related processes, reducing the risk of unnecessary administrative actions.
Original PR description
Three fields were missing in the copying process from the contract template Forward-Port-Of: odoo/enterprise#124235
New planning slots now use the company’s working hours in the company timezone, so default start and end times appear correctly. This prevents users from seeing shifted hours when creating schedule entries for companies in non-UTC timezones.
Original PR description
Issue: ---------------------------------------- When creating a new slot, no resrouces are set so we use the calendar of the company but the hours are offset because of the timezone. Steps to reproduce: ---------------------------------------- - Have planning Installed - Have an hour based calendar, from 8 to 16 each day for example - Have the company timezone in UTC+2, same for you the user - Go in Planning "Schedule By Resource" view - Click "New" - The default start and end time are 10am and 6pm (2h offset) Cause: ---------------------------------------- `default_get()` calls `_company_working_hours()` to get the company calendar hours. But they are returned in UTC, so when displaying them they are converted to the user timezone and are offsetted. Solution: ---------------------------------------- `_company_working_hours()` should return the compny hours in the company timezone. opw-6333993 Forward-Port-Of: odoo/enterprise#123033
Payslip reports in Belgian payroll now correctly show eco voucher lines again. This prevents missing benefit information after the eco voucher setup was changed, helping employees and payroll teams see accurate payslip details.
Original PR description
Since changing Eco vouchers to property input, the eco vouchers line on the report does not appear, this commit fixes it by calling the correct method in the template task-6370164
Automatic 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
A new test checks that overtime is calculated correctly for employees with flexible schedules when leave is involved. This helps prevent payroll or time tracking errors from reappearing in future updates.
Original PR description
For PR: https://github.com/odoo/odoo/pull/274831 This commit adds a test case to ensure that overtime is correctly calculated for the flexible employee opw-6259328,6284145 Forward-Port-Of: odoo/enterprise#123830
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
Subscription product pages now correctly show the original price crossed out next to the Buy Once price when one-time purchases are enabled. This makes discounts or price comparisons clearer for shoppers and helps avoid confusion during purchase decisions.
Original PR description
Version - saas-19.1 Steps to reproduce: - Enable 'Accept One Time Sale' on a subscription product - Open the product page on the website Issue: For subscription products with one time sale enabled, the original price was not shown as a strikethrough next to the Buy Once price. Fix: - Captured and exposed the original price to the template before it gets overwritten during subscription price processing - Added the missing strikethrough element to the Buy Once section of the product page Task ID - 6260207 Forward-Port-Of: odoo/enterprise#119488
Managers will no longer see the Print option twice in the Planning Gantt view. This keeps the interface cleaner and avoids confusion when using planning actions.
Original PR description
Issue: - Managers see the "Print" action twice in the Gantt view: once as a standalone button and once in the Actions dropdown. Cause: - The standalone Print button is guarded on `!this.isManager`, but `isManager` lives on the model. The expression is therefore always truthy, so the button always renders. Fix: - Use `!this.model.isManager` instead. task-6364971
Fixed demo-mode social feed comments so they use the correct built-in demo contact data after older demo data was removed. This ensures comment authors display the right profile image in demo feeds, making demonstrations look consistent and credible.
Original PR description
Bug === Since ce264a2 , we remove the demo partner in the social_demo module, but we didn't update the code to use the demo data in base. Task-6293738 Forward-Port-Of: odoo/enterprise#124151 Forward-Port-Of: odoo/enterprise#120821
The AI chatbox now appears in front of key website editor controls, including the toolbar and snippet selector dialog. This prevents the assistant from being hidden during editing, especially when mass mailing features are installed.
Original PR description
This PR addresses two problems relative to the AI chatbox z-index. 1. AI chatbox should appear above the toolbar, but used to appear below instead. 2. AI chatbox should appear above snippet selector dialog, but used to appear below if `mass_mailing` was installed. task-6366360
AI conversations will no longer fail just because the automatic chat title update encounters an error. This keeps the user's AI exchange running smoothly, while a test now confirms the issue stays fixed.
Original PR description
Before this commit, if there was an error during the ai chat renaming process, the whole request would fail. That was the case because in the `generate_response` controller method, we would try-catch the `_generate_channel_name` method and if an exception was caught we would return with the raised error. Renaming the chat is not a critical process. Even if it fails, the user conversation with the AI can continue normally. After this commit, instead of returning the caught exceptions, we just continue without handling them. Also in this commit, a test was added to check that an exception doesn't block the rest of the generate_response function. Task-6356851
Users can now return from a budget report detail page to the report list without seeing an error. The budget report now uses a valid default sorting order, preventing a crash during normal breadcrumb navigation.
Original PR description
Problem:
The `budget.report` model had its default sorting (`_order`) set to False. When a user navigates back to the report list view via the breadcrumbs, the web client invokes `web_read_group`, which runs `self._order.split(',')`. Because `_order` is a boolean rather than a string, this raises an AttributeError and throws an RPC_ERROR.
Solution:
Set `_order = 'date desc'` on `budget.report`. Both queries within the `_table_query` UNION ALL expose a `date` column, providing a semantically correct and safe default ordering constraint.
Steps to replicate:
- Go to Accounting > Accounting > Analytic Budgets.
- Select any budget.
- Click 'Audit' on any budget line to land on the budget report view.
- Click to open any individual record.
- Navigate back using the breadcrumbs.
- -> RPC_ERROR: AttributeError: 'bool' object has no attribute 'split'
opw-6372610
Forward-Port-Of: odoo/enterprise#12419112 changes
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
Shopee order lines now show the SKU for the specific product variant purchased, instead of defaulting to the general product template SKU. This makes sales order descriptions clearer and helps teams identify the exact item ordered when listings include variants.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
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
Payroll-related processes now explicitly filter out archived records when checking relevant versions. This helps prevent inactive or outdated payroll data from being used accidentally, improving reliability without changing user workflows.
Original PR description
We cannot assume in methods that the active_test is set. Therefore, we should always add active=True in search domains.
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
Payroll schedule choices now appear in the user's selected language across multiple country-specific payroll apps. This helps employees and payroll teams using French or other languages understand salary payment frequency labels correctly.
Original PR description
Issue: ---------------------------------------- The values of the field `schedule_pay` aren't translated. Steps to reproduce: ---------------------------------------- - Switch the language to French - Open an employee form, "Paie" tab - The selection in the "Salaire" tab is not translated to French Cause: ---------------------------------------- When the selection values were moved to a method in 7a123d71925b25f26ba0a8abff0c4a159147bdd0. The strings were not declared as translatable. opw-6359395 Forward-Port-Of: odoo/enterprise#123718
This fix prevents errors when payroll users add Mexican salary-related fields to payslip forms using Odoo Studio or create a new off-cycle payslip before selecting an employee. The fields now display safely, helping users verify payroll calculations without being blocked by an unexpected crash.
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#121718This 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
Fixed demo-mode social feed comments so they use the standard demo contact data after the module-specific demo partner was removed. This ensures comment authors display the correct image in feed views, keeping demo environments consistent and easier to evaluate.
Original PR description
Bug === Since ce264a2 , we remove the demo partner in the social_demo module, but we didn't update the code to use the demo data in base. Task-6293738 Forward-Port-Of: odoo/enterprise#124151 Forward-Port-Of: odoo/enterprise#120821
Customers viewing subscription products with a one-time purchase option now see the original price crossed out next to the Buy Once price. This makes discounts or price comparisons clearer and helps shoppers better understand the offer before purchasing.
Original PR description
Version - saas-19.1 Steps to reproduce: - Enable 'Accept One Time Sale' on a subscription product - Open the product page on the website Issue: For subscription products with one time sale enabled, the original price was not shown as a strikethrough next to the Buy Once price. Fix: - Captured and exposed the original price to the template before it gets overwritten during subscription price processing - Added the missing strikethrough element to the Buy Once section of the product page Task ID - 6260207 Forward-Port-Of: odoo/enterprise#119488
Fixes an error that could occur when users returned to the budget report list using breadcrumbs after opening a report record. This keeps analytic budget audit navigation working smoothly and prevents an unexpected RPC error.
Original PR description
Problem:
The `budget.report` model had its default sorting (`_order`) set to False. When a user navigates back to the report list view via the breadcrumbs, the web client invokes `web_read_group`, which runs `self._order.split(',')`. Because `_order` is a boolean rather than a string, this raises an AttributeError and throws an RPC_ERROR.
Solution:
Set `_order = 'date desc'` on `budget.report`. Both queries within the `_table_query` UNION ALL expose a `date` column, providing a semantically correct and safe default ordering constraint.
Steps to replicate:
- Go to Accounting > Accounting > Analytic Budgets.
- Select any budget.
- Click 'Audit' on any budget line to land on the budget report view.
- Click to open any individual record.
- Navigate back using the breadcrumbs.
- -> RPC_ERROR: AttributeError: 'bool' object has no attribute 'split'
opw-6372610
Forward-Port-Of: odoo/enterprise#12419116 changes
Resolved issues and error corrections
Fixes an error that could appear when users returned to the budget report list using breadcrumbs after opening a report entry. Budget reports now have a safe default order, so users can continue reviewing analytic budget details without interruption.
Original PR description
Problem:
The `budget.report` model had its default sorting (`_order`) set to False. When a user navigates back to the report list view via the breadcrumbs, the web client invokes `web_read_group`, which runs `self._order.split(',')`. Because `_order` is a boolean rather than a string, this raises an AttributeError and throws an RPC_ERROR.
Solution:
Set `_order = 'date desc'` on `budget.report`. Both queries within the `_table_query` UNION ALL expose a `date` column, providing a semantically correct and safe default ordering constraint.
Steps to replicate:
- Go to Accounting > Accounting > Analytic Budgets.
- Select any budget.
- Click 'Audit' on any budget line to land on the budget report view.
- Click to open any individual record.
- Navigate back using the breadcrumbs.
- -> RPC_ERROR: AttributeError: 'bool' object has no attribute 'split'
opw-6372610
Forward-Port-Of: odoo/enterprise#124191This 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#121718This fix updates the Belgian payroll rules so the 3000 deduction is correctly applied for the second and third quarters of 2026. It helps ensure payroll calculations remain aligned with Belgian payroll requirements during that period.
Original PR description
Forward-Port-Of: odoo/enterprise#124034
Payroll schedule options now appear in the user's selected language across multiple country payroll modules. This fixes untranslated salary payment frequency labels, improving usability for employees and HR teams working in non-English languages.
Original PR description
Issue: ---------------------------------------- The values of the field `schedule_pay` aren't translated. Steps to reproduce: ---------------------------------------- - Switch the language to French - Open an employee form, "Paie" tab - The selection in the "Salaire" tab is not translated to French Cause: ---------------------------------------- When the selection values were moved to a method in 7a123d71925b25f26ba0a8abff0c4a159147bdd0. The strings were not declared as translatable. opw-6359395 Forward-Port-Of: odoo/enterprise#123718
Shopee order lines now show the SKU for the specific product variant ordered, rather than the general template SKU. This makes order descriptions clearer and helps teams identify the exact item sold when listings include variants.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
Creating certificates in settings no longer fails when a Peruvian company is used alongside the Chilean localization. The Chile-specific serial number requirement is now limited to the relevant Chilean context, avoiding unnecessary setup errors for other Latin American companies.
Original PR description
With a l10n_pe company and having a l10n_cl company installed: - Try to create a certificate in the settings, there is a missing field error. The template certificate_certificate_view_form have a required subject_serial_number field in l10n_cl but it shouldn't in other latam localization. opw-6274126 Forward-Port-Of: odoo/enterprise#120211
Regular 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
This fix prevents an error when opening Studio from the Working Files menu and view. It improves reliability for users customizing or reviewing working files, with no expected change to normal business workflows.
Original PR description
Open Studio while on "Working Files" menu and view. Before this commit, the python raised an error becaude at some point `record[False]` (returning the current virtual record) was put in the return values of the onchange. After this commit, there is no error. runbot-error-941248
The Trial Balance report now handles load-more rows even when some column information is empty. This prevents an error for users reviewing partner-grouped balances, improving reliability when navigating accounting reports.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451
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
This fixes an issue where the signing interface could fail in debug mode when extra page markers were present. The change helps keep document signing reliable for users working with customized or inherited templates.
Original PR description
Use lastElementChild when retrieving the sign item from the target element. In debug mode, inherited templates may introduce HTML comments into the DOM. Since lastChild return a comment node, accessing classList on the returned node raises an error. Using lastElementChild ensures that the last HTML element is always retrieved, regardless of comment nodes in the DOM. Forward-Port-Of: odoo/enterprise#122106
The Dutch reports module information no longer shows an outdated website link that now points to unrelated content. This prevents users from being sent to the wrong site and keeps the module details accurate.
Original PR description
The URL leads to a website that has nothing to do with what it used to be so it needs to be removed. Task-6360682 Forward-Port-Of: odoo/enterprise#124155 Forward-Port-Of: odoo/enterprise#123019
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
Opening Studio from a project task list now keeps the browser URL clean and avoids adding an incorrect extra project or task identifier. Users can also use the browser back button or load the Studio URL directly without running into navigation errors.
Original PR description
Go on a project, then open its task list view Open studio with the menu item. At this point, studio is open but the url looks like: `/odoo/project/5/tasks/studio/5` the last `/5` is wrong ; this commit fixes this. Then, hit the browser's back button. There is an error because the active_id was not correctly set when leaving studio that way Try loading `/odoo/project/5/tasks/studio`, again, there is an error because the active_id is read from the wrong object Forward-Port-Of: odoo/enterprise#122405
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
8 changes
Resolved issues and error corrections
French VAT reports sent through Aspone now use the latest reporting year, ensuring submitted forms match current requirements. This helps businesses avoid filing issues caused by outdated form versions.
Original PR description
This commit will put the new millesime for all the form that we send though aspone. (Was done in 19.0 here: https://github.com/odoo/enterprise/commit/48454123fc4a419e22648df05e0e3c3bf892a277) task-6253745 Forward-Port-Of: odoo/enterprise#124129
Shopee order lines now use the correct variant SKU in their descriptions instead of falling back to the general product template SKU. This helps users identify the exact product variant sold and avoids confusion when reviewing orders with variants.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
This fix ensures a Belgian payroll rule for employee termination holidays is attached to the correct salary structure. It helps payroll calculations use the intended rules, reducing the risk of incorrect payslip results for affected Belgian employees.
Original PR description
Oversight of 553ba7d0d066b4179b7f89f8ec9ef8f0bffe964d Forward-Port-Of: odoo/enterprise#124331 Forward-Port-Of: odoo/enterprise#123765
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
Opening Studio from a project task list now keeps the web address clean and avoids adding an extra project identifier. Browser back navigation and direct Studio links also work reliably, preventing errors for users customizing project task views.
Original PR description
Go on a project, then open its task list view Open studio with the menu item. At this point, studio is open but the url looks like: `/odoo/project/5/tasks/studio/5` the last `/5` is wrong ; this commit fixes this. Then, hit the browser's back button. There is an error because the active_id was not correctly set when leaving studio that way Try loading `/odoo/project/5/tasks/studio`, again, there is an error because the active_id is read from the wrong object Forward-Port-Of: odoo/enterprise#122405
The Dutch reports module no longer shows an outdated website link that now points to unrelated content. This avoids confusing users or directing them to an irrelevant external site.
Original PR description
The URL leads to a website that has nothing to do with what it used to be so it needs to be removed. Task-6360682 Forward-Port-Of: odoo/enterprise#124155 Forward-Port-Of: odoo/enterprise#123019
8 changes
Resolved issues and error corrections
Shopee order line descriptions now use the specific variant SKU when a product listing has variants, instead of showing the general product template SKU. This makes sales orders clearer and helps teams identify the exact product variant sold.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
A Belgian payroll rule for employee termination holidays is now linked to the correct payroll structure. This helps ensure affected payslips are calculated and validated consistently, reducing payroll processing errors.
Original PR description
Oversight of 553ba7d0d066b4179b7f89f8ec9ef8f0bffe964d Forward-Port-Of: odoo/enterprise#124331 Forward-Port-Of: odoo/enterprise#123765
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
French VAT report forms sent through Aspone now use the updated filing year reference. This helps ensure submitted forms match the expected current administrative format and reduces the risk of filing rejections.
Original PR description
This commit will put the new millesime for all the form that we send though aspone. (Was done in 19.0 here: https://github.com/odoo/enterprise/commit/48454123fc4a419e22648df05e0e3c3bf892a277) task-6253745 Forward-Port-Of: odoo/enterprise#124129
Opening Studio from a project task list now keeps the browser address clean and accurate. Users can also use the browser back button or reload the Studio page without hitting an error, improving reliability during customization work.
Original PR description
Go on a project, then open its task list view Open studio with the menu item. At this point, studio is open but the url looks like: `/odoo/project/5/tasks/studio/5` the last `/5` is wrong ; this commit fixes this. Then, hit the browser's back button. There is an error because the active_id was not correctly set when leaving studio that way Try loading `/odoo/project/5/tasks/studio`, again, there is an error because the active_id is read from the wrong object Forward-Port-Of: odoo/enterprise#122405
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
5 changes
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
Payslips sent by email now show a neutral message saying they were sent, instead of incorrectly saying they were re-sent on the first send. When sending payslips for multiple employees, each payslip now receives only one chatter note, reducing confusion in payroll records.
Original PR description
**Issue:** Clicking Send By Email on a payslip opens the hr.payslip.send.mail wizard. Its action_send() always logs "The payslip has been re-send to the employee." in the payslip chatter, even when…
**Issue:** Clicking Send By Email on a payslip opens the hr.payslip.send.mail wizard. Its action_send() always logs "The payslip has been re-send to the employee." in the payslip chatter, even when the payslip is being sent for the first time. The log call also runs inside the loop over the employees and goes through all the payslips of the wizard on each pass, so when the wizard sends payslips of several employees every payslip gets the same note once per employee. This started with the rework of the wizard in https://github.com/odoo/enterprise/commit/39e0488a7e076ee648b47cc3d1cad41cadfd692e **Fix:** The wizard cannot tell a first send from a resend. There is no field on the payslip that keeps track of a previous send, and the chatter cannot be used for that either because the mail sent automatically on validation can be deleted after sending. The fix changes the log in action_send() to say the payslip has been sent by email, which is true in both cases, and moves it out of the employee loop so each payslip gets exactly one note. **Steps to reproduce:** 1. In Payroll > Configuration > Settings, set "Send payslips to employees" to When Paid and save 2. In Payroll > Payslips, create an off-cycle payslip for an employee, click Compute, then Validate 3. Go back to the settings and set "Send payslips to employees" to When Confirmed 4. On the payslip, click Pay, then Mark as Paid 5. Click Print so the payslip document is generated 6. Click Send By Email and send the mail 7. Check the payslip chatter => The chatter shows "The payslip has been re-send to the employee." while the payslip was never sent before Ticket [link](https://www.odoo.com/odoo/project.task/6324204) opw-6324204 Forward-Port-Of: odoo/enterprise#123298
Chilean export invoice PDFs now keep customs information in the correct columns even when origin or destination port details are missing. This prevents package quantities and other export details from appearing under the wrong headings, improving document accuracy for customers and customs processes.
Original PR description
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by…
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by QWeb, causing the remaining columns to shift left This results in `Qty of Packages` appearing under `Origin Port` or `Destination Port` in the printed document ### Cause: `l10n_cl_port_origin_id` and `l10n_cl_port_destination_id` have no default value and are optional fields `t-out` on a falsy value omits the `td` entirely in QWeb, breaking the column alignment Adding `or ''` ensures an empty `td` is always rendered, preserving the table structure regardless of whether the fields are set ### Steps to reproduce: - Install `l10n_cl_edi_exports` and switch to CL Company - Create an Invoice (any customer, any line) - In the gear menu, select Print > Invoice PDF copy (Chile) Before the fix, `Qty of Packages` appears under `Origin Port` when neither port field is set opw-6304670 Forward-Port-Of: odoo/enterprise#123150 Forward-Port-Of: odoo/enterprise#121923
Belgian termination holiday attest payslips now use the employee's private address directly, so the address is shown correctly in the required places. This helps ensure departing employees receive complete and accurate payroll documents.
Original PR description
[FIX] l10n_be: missing employee address on holiday attest Bug reproduction: Belgium -> create employee -> fire the employee -> look to the holiday attest payslips (N and N-1) -> private address of the employee is missing in 2 places in payslip Bug cause: o.employee_id.work_contact_id work contact id was used in report but we can just use private_street, private_city etc. instead. Bug solution: Use private_street, private_city etc. fields directly from the employee model. task - 6361457 Forward-Port-Of: odoo/enterprise#123528
14 changes
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-6267003Fixed an issue that could cause an error when users returned to the budget report list using breadcrumbs. This keeps the Analytic Budgets workflow smooth and prevents an unexpected interruption during budget review.
Original PR description
Problem:
The `budget.report` model had its default sorting (`_order`) set to False. When a user navigates back to the report list view via the breadcrumbs, the web client invokes `web_read_group`, which runs `self._order.split(',')`. Because `_order` is a boolean rather than a string, this raises an AttributeError and throws an RPC_ERROR.
Solution:
Set `_order = 'date desc'` on `budget.report`. Both queries within the `_table_query` UNION ALL expose a `date` column, providing a semantically correct and safe default ordering constraint.
Steps to replicate:
- Go to Accounting > Accounting > Analytic Budgets.
- Select any budget.
- Click 'Audit' on any budget line to land on the budget report view.
- Click to open any individual record.
- Navigate back using the breadcrumbs.
- -> RPC_ERROR: AttributeError: 'bool' object has no attribute 'split'
opw-6372610Shopee order lines now show the SKU for the exact product variant ordered instead of the broader product template SKU. This helps sales teams and customers see the correct item details on orders when listings include variants.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124031
This fixes a Belgian payroll configuration issue where a payroll rule for employee termination holidays was assigned to the wrong salary structure. The correction helps ensure affected payslips are calculated and validated against the appropriate payroll setup.
Original PR description
Oversight of 553ba7d0d066b4179b7f89f8ec9ef8f0bffe964d Forward-Port-Of: odoo/enterprise#124331 Forward-Port-Of: odoo/enterprise#123765
The Dutch reports module no longer shows an outdated website link in its module information. This prevents users from being directed to an unrelated external site and keeps the module details accurate.
Original PR description
The URL leads to a website that has nothing to do with what it used to be so it needs to be removed. Task-6360682 Forward-Port-Of: odoo/enterprise#124155 Forward-Port-Of: odoo/enterprise#123019
This fixes an internal payroll issue where reused rule settings could be unintentionally altered during calculations. Payroll rules now receive a safe copy of these settings, reducing the risk of inconsistent or hard-to-trace payroll results.
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#123057This fix ensures the express mention in French VAT report files is placed in the correct part of the submission sent to Aspone. This helps avoid rejection or processing issues caused by the mention being included in an unsupported section.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745
Opening Studio from a project task list now keeps the browser address clean and correctly tracks the active project context. This prevents errors when users go back in the browser or open a Studio URL directly.
Original PR description
Go on a project, then open its task list view Open studio with the menu item. At this point, studio is open but the url looks like: `/odoo/project/5/tasks/studio/5` the last `/5` is wrong ; this commit fixes this. Then, hit the browser's back button. There is an error because the active_id was not correctly set when leaving studio that way Try loading `/odoo/project/5/tasks/studio`, again, there is an error because the active_id is read from the wrong object Forward-Port-Of: odoo/enterprise#122405
When a new employee contract is created from a template, its analytic distribution is now copied correctly. This prevents missing payroll cost allocation information and reduces the need for manual correction after contract creation.
Original PR description
Problem: When creating a new contract from a template, the analytic distribution field is not copied from the template to the contract. Steps to reproduce: 1. Create a contract template with an analytic distribution. 2. Create a new contract for an employee from the template. 3. Check the analytic distribution field on the new contract. 4. Notice how the analytic distribution field is empty, even though it was set on the template. Cause: The field is not included in the list of whitelisted fields to copy from the template. https://github.com/odoo/odoo/blob/0133e46f89df7dce8c39d2bacd29579d57a83fad/addons/hr/models/hr_version.py#L443 opw-6370781
This fixes a display issue where the CFDI Origen field could disappear from Mexican invoice forms when the Colombian e-invoicing module was also installed. Users working with Mexican electronic invoicing can now reliably access the needed field without module conflicts.
Original PR description
The field 'CFDI Origen' (l10n_mx_edi_cfdi_origin) is not visible on the account move form view if l10n_co_edi module is installed because this https://github.com/odoo/enterprise/blob/19.0/l10n_co_edi/views/account_invoice_views.xml#L10 is the last group on ="//sheet/group//group[last()]" and it is invisible for mx. This commit fixes that. I created this issue https://github.com/odoo/odoo/issues/276358 reporting the bug. Task Adhoc side: 67269
Opening 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
10 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
Philippine check printing now rounds the cents portion of written amounts to two decimals, even when the currency is configured with more precision. This prevents confusing or incorrect check text such as showing four decimal digits in the amount in words.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#121913
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
The point of sale IoT integration now works better with newer IoT Boxes that no longer report certain device details. This prevents searches from relying on missing information, helping printers and SIX payment terminals be found correctly.
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
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
This fix makes product creation permission checks in the barcode lookup point of sale flow happen consistently and immediately. It helps ensure users only see or use product creation options when they have the right access, reducing confusing behavior at checkout.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420
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
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