Tuesday, March 10, 2026
32 changes · saas-19.1
New functionality added to Odoo
This update introduces a 'Net Cost' salary rule specifically for Saudi Arabia payroll, addressing a previous inconsistency in how employee costs were calculated. This change ensures accurate deductions and employer contributions, particularly for rules like the GOSI Employee Rule, improving payroll accuracy and compliance.
Original PR description
This PR introduces a new salary rule 'Net Cost' since setting appears_on_employee_cost_dashboard as True on the salary rule considers the sign on the rule, and for cases like the GOSI Employee Rule we need the sign to be negative to deduct from the employee but also increase the employer contribution amount. - adjusted provision rules to be part of a new category - adjusted remaining days to be allowance instead of company contribution - NET salary doesn't contribute to employer cost - New salary rule 'net cost' contributes to employer cost. Task-5894405 Forward-Port-Of: odoo/enterprise#106834
Resolved issues and error corrections
This update corrects a bug where the valuation of kit components was incorrectly calculated after vendor bills were processed. The system was failing to account for the proportional share of the kit's cost, leading to inflated component values. This fix ensures accurate valuation of kits, particularly when using vendor bills.
Original PR description
**Issue**: Billing a PO containing kit with several components can lead to incorrect valuation of its components **Steps to reproduce**: - Create a kit product (by creating a BOM with 2 components)…
**Issue**: Billing a PO containing kit with several components can lead to incorrect valuation of its components **Steps to reproduce**: - Create a kit product (by creating a BOM with 2 components) with AVCO valuation - Create a PO for 1 unit at unit price 10 - Confirm PO and validate the receipt - Go to the BOM of the kit product and check BOM overview -> The cost of the two components are 5, which is correct - Go to Accounting > Vendors > Bill - Create a new bill by indicating the PO in "Auto-Complete" field and validate - Go back to the BOM of the kit product and check BOM overview -> The cost of the two components are 10, which is correct This also occurs with FIFO valuation **Cause**: While computing the value of the move: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L282 https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L313-L314 It checks the value of the Bill: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L357-L358 Which relies directly on the AML price of the kit: https://github.com/odoo/odoo/blob/a2b3a10255dba290ea462b9193ae11c54d8dd5e0/addons/purchase_stock/models/stock_move.py#L170 This ignores the `cost_share` of each BOM component. As a result, each component receives the full kit value instead of its proportional share This means that the value of the move is 10 instead of 10/2=5, which makes the valuation computation wrong: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/product.py#L393 **Aditionnal note** The computation of the quantity is also incorrect: https://github.com/odoo/odoo/blob/a2b3a10255dba290ea462b9193ae11c54d8dd5e0/addons/purchase_stock/models/stock_move.py#L169 since it assumes the quantity of component of the kit is the same than the quantity of the kit itself, which is not true in the general case. opw-5924940 Forward-Port-Of: odoo/odoo#249264
This change resolves an issue preventing the l10n_mx_edi_pos module from correctly updating invoices when POS data is involved. The fix adds a necessary permission to access `pos.order` records, allowing the module to generate invoices accurately. This ensures proper integration with point-of-sale transactions in Mexico.
Original PR description
`l10n_mx_edi_pos` is now populating `pos_order_ids` [1]. l10n_mx_edi_pos is designed to send POS data into MX EDI without giving accounting users direct access to pos.order. So, we should consider…
`l10n_mx_edi_pos` is now populating `pos_order_ids` [1]. l10n_mx_edi_pos is designed to send POS data into MX EDI without giving accounting users direct access to pos.order. So, we should consider that in this module we won't have access to:
- `pos_order_ids` m2m on `l10n_mx_edi.document` (caused problems before [2])
- `pos_order_ids` o2m on `account.move`
- `pos.order` model
We add a minimal `sudo()` in
`_create_update_invoice_document_from_invoice` to be able to read from the `pos_order_ids` field on `account.move`:
```
File "/e19-1/l10n_mx_edi/models/account_move.py", line 1551, in _l10n_mx_edi_cfdi_invoice_document_cancel
return self.env['l10n_mx_edi.document']._create_update_invoice_document_from_invoice(self, document_values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/e19-1/l10n_mx_edi_pos/models/l10n_mx_edi_document.py", line 54, in _create_update_invoice_document_from_invoice
if invoice.pos_order_ids:
^^^^^^^^^^^^^^^^^^^^^
File "/c19-1/odoo/orm/fields_relational.py", line 967, in __get__
return super().__get__(records, owner)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/c19-1/odoo/orm/fields_relational.py", line 45, in __get__
return super().__get__(records, owner)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/c19-1/odoo/orm/fields.py", line 1743, in __get__
recs._fetch_field(self)
File "/c19-1/odoo/orm/models.py", line 3015, in _fetch_field
self.fetch(fnames)
File "/c19-1/odoo/orm/models.py", line 3055, in fetch
fetched = self._fetch_query(query, fields_to_fetch)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/c19-1/odoo/orm/models.py", line 3193, in _fetch_query
field.read(fetched)
File "/c19-1/odoo/orm/fields_relational.py", line 985, in read
raise AccessError(records.env._("Failed to read field %s", self) + '\n' + str(e)) from e
odoo.exceptions.AccessError: Failed to read field account.move.pos_order_ids
You are not allowed to access 'Point of Sale Order' (pos.order) records.
This operation is allowed for the following groups:
- Inventory/User
- Point of Sale/User
```
Afterwards `_create_update_document` in `l10n_mx_edi` will create or write this `pos_order_ids` value on the document without `sudo()`:
```
File "/home/jvo/Code/odoo/trees/e19-1/l10n_mx_edi/models/account_move.py", line 1551, in _l10n_mx_edi_cfdi_invoice_document_cancel
return self.env['l10n_mx_edi.document']._create_update_invoice_document_from_invoice(self, document_values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/e19-1/l10n_mx_edi_pos/models/l10n_mx_edi_document.py", line 56, in _create_update_invoice_document_from_invoice
return super()._create_update_invoice_document_from_invoice(invoice, document_values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/e19-1/l10n_mx_edi/models/l10n_mx_edi_document.py", line 1969, in _create_update_invoice_document_from_invoice
document = remaining_documents._create_update_document(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/e19-1/l10n_mx_edi/models/l10n_mx_edi_document.py", line 1936, in _create_update_document
result_document = self.create({
^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/decorators.py", line 365, in create
return method(self, vals_list)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/models.py", line 4021, in create
records = self._create(data_list)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/models.py", line 4253, in _create
field.create([
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/fields_relational.py", line 760, in create
self.write_batch(record_values, True)
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/fields_relational.py", line 786, in write_batch
self.write_real(records_commands_list, create)
File "/home/jvo/Code/odoo/trees/c19-1/odoo/orm/fields_relational.py", line 1559, in write_real
raise AccessError(model.env._("Failed to write field %s", self) + "\n" + str(e))
odoo.exceptions.AccessError: Failed to write field l10n_mx_edi.document.pos_order_ids
You are not allowed to access 'Point of Sale Order' (pos.order) records.
This operation is allowed for the following groups:
- Inventory/User
- Point of Sale/User
```
We therefore take out `pos_order_ids` in an override and write it ourselves with another minimal `sudo()`.
[1] https://github.com/odoo/enterprise/pull/97060
[2] https://github.com/odoo/enterprise/pull/99590
opw-6000974This update allows administrators to view and revoke user sessions, enhancing security and control over access to the Odoo system. The change improves administrative workflows by providing a dedicated view for managing user sessions, aligning with best practices for user access control.
Original PR description
An administrator must be able to revoke other users' sessions. The revocation action has been moved to the `res.session` model. Add the view that allows admins to view user sessions and revoke them. Task-5941823
This update fixes an issue where overtime calculations were incorrect for employees working night shifts that crossed midnight. The change ensures accurate overtime tracking by properly handling time zone differences and correctly deleting outdated overtime records, preventing duplicated hours. This improves the reliability of employee time tracking.
Original PR description
**Steps to reproduce:** 1. Configure Working Hours: Set up a night-shift schedule that splits at midnight (Local Time): - Thursday: 20:00 to 24:00 - Friday: 00:00 to 04:00 2. Assign the above…
**Steps to reproduce:** 1. Configure Working Hours: Set up a night-shift schedule that splits at midnight (Local Time): - Thursday: 20:00 to 24:00 - Friday: 00:00 to 04:00 2. Assign the above calendar to an employee. 3. Set the Employee’s Timezone to Asia/Kolkata (UTC+5:30). 4. Assign an active Overtime Ruleset to the employee. 5. When the attendance calendar is in Europe/Brussels TZ - Check-in: Jan 15, 15:30 CET - Check-out: Jan 15, 23:30 CET Expected Behavior: Worked Hours = 8.0, Overtime (Extra Hours) = 0.0 Actual Behavior (Bug): Worked Hours = 8.0, Overtime = 4.0 **Bug Cause:** 1. The _update_overtime function normalized the Ruleset version periods using time.min for both the start and end of the day. This forced the validity period of the rules to end exactly at 00:00:00 UTC on the final day. 2. The overtime recalculation logic failed to delete existing overtime records because the search domain was incorrectly computed. Specifically, using relativedelta(SU) and relativedelta(MO(-1)) without the weekday= keyword argument did not shift the dates to the week boundaries. This resulted in an empty or incorrect deletion range, leading to duplicated overtime hours as new records were layered on top of un-removed old ones. **Solution:** 1. Modified the version_periods_by_employee mapping to use time.max (23:59:59) for the end of the version period. This ensures that the ruleset remains active through the entire final calendar day in UTC, allowing shifts that cross the midnight boundary to be fully captured. 2. Corrected the date range logic by explicitly passing the weekday argument to relativedelta. This ensures the domain correctly targets the full week window - from the preceding Monday to the following Sunday, ensuring all relevant stale overtime lines are purged before recalculation. 3. Updated Manual Edit Handling: Refined the logic to detect days with manual overrides or "To Approve" statuses before unlinking. If an attendance change triggers a recalculation on such a day, the system now replaces the manual entry with the mathematically correct value but flags the new record with a to_approve status for manager review. 4. Adjusted the expected overtime in test_weekly_overtime to 18.0 to correctly reflect the cumulative calculation of daily overtime (2h/day) plus the weekly overtime threshold reached on Friday. Task: 5710273 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where discounts weren't correctly applied to split POS orders, leading to incorrect discount calculations. The fix ensures that discounts are accurately added to each split order line, improving the reliability of split payment processing for restaurant and loyalty programs. This resolves a bug that prevented accurate discount application during split order transactions.
Original PR description
**: discount, loyalty, restaurant Steps: --- - Create a POS order with at least 2 quantities. - Apply a global discount (e.g., 10%). - Split the order with 1 quantity. - Split again with the remaining 1 quantity. - After validating the final split payment, go back to Split again. Issue: --- - Clicking Split again shows a negative discount amount. - The split orders do not contain any discount line. Cause: --- - The discount line was added to the current order instead of the split order. - When all lines were split, the current order was reused instead of creating a new one. Fix: --- - Add the discount line to the correct split order. - Avoid creating a new order when all lines are already split. task-5942356 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where users without project access rights would encounter errors when modifying work orders linked to private projects. The fix ensures that workers can successfully update these work orders by granting necessary read permissions to project data, preventing access errors.
Original PR description
When working on a MO that is linked to a project in private, it will trigger a access error if the worker is does not have project access right Steps to reproduce: ------------------- * Install Project, MRP, Accouting * Create a private project * Create a MO and link it to this project * confirm this MO with a user that has no project access right Observation: ------------- When modifying the MO, we will pass through the write that has been overwritten: https://github.com/odoo/enterprise/blob/b332af45a46b2295797a5096f68b7953554a495b/project_mrp_workorder_account/models/mrp_production.py#L6-L10 we will call _get_analytic_distribution on project.project and since _get_analytic_distribution will [read fields from self](https://github.com/odoo/odoo/blob/436921c24a531eba6bf57ffe3f7c3b4978139d83/addons/analytic/models/analytic_line.py#L59-L64) we need project.project read rights. opw-4919576 Forward-Port-Of: odoo/enterprise#108148
This update resolves an issue where early payment discounts weren't correctly processed when generating invoices in the Factur-X format. The change adds the necessary handling for Early Payment Discounts (EPD) within this format, ensuring accurate invoice generation and compliance. This improves the accuracy of financial reporting.
Original PR description
Added the handling of early payment discount in the factur-x format. opw-5265981 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252098 Forward-Port-Of: odoo/odoo#244659
This update resolves an issue where temporarily disabled products weren't appearing correctly in the self-order POS configuration. The fix ensures that product snoozes are now accurately reflected in real-time, allowing cashiers to manage product availability effectively. This improves the user experience and operational accuracy of the self-order system.
Original PR description
The `pos_snooze_ids` was not included in the `load_pos_self_data_fields` so the field was not accessible in the config in self and it would not display the temporary disabled products. I added it now so that products will be disabled in real time based on updates from the cashier screen --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A recent update caused errors in Odoo logs when using domains with computed fields in automation rules or record filters. This fix ensures that domains are properly validated, preventing unexpected behavior and improving data consistency. The change reverts a previous refactoring to correctly evaluate domain expressions.
Original PR description
An error is generated in the logs when a user opens a record after saving a computed field used in the domain, as demonstrated in the steps below. Step1: - install `crm` and `base_automation` -…
An error is generated in the logs when a user opens a record after saving a computed field used in the domain, as demonstrated in the steps below.
Step1:
- install `crm` and `base_automation`
- Create a new automation rule for the `Activity` module and set the `Apply On` domain as below: `[("res_model", "=", "crm.lead"), ("state","=","done")]`
- An error will occur in the log when you open this record.
Step 2:
- Install `mass_mailing`
- Go to Email Marketing and create a record as below data
- Recipients: `Contact`
- Set domain as `[("vat_label", "=", 'test')]`
- An error will occur in the log when user open this record.
This issue occurred because the recently refactored commit [1] used `validate` of Domain for the domain instead of `search_count`. The `validate` method only checks the structure of the domain and does not verify whether the domain is actually executed or not.
This commit fixes the issue by reverting commit [1], restoring the previous behavior where the domain is evaluated using `search_count`.
[1]: https://github.com/odoo/odoo/commit/a1434c32e9f4dd226d512677fd96e3051b908d8b
sentry-7004977102This update resolves an issue causing the floor screen to repeatedly refresh, impacting the user experience. The problem stemmed from a code change that incorrectly modified appointment start times, triggering an endless loop of re-renders. This fix ensures a stable and reliable booking process.
Original PR description
Infinite re-rendering in floor_screen.
Root cause: `getFirstAppointment` mutates reactive model state
(appointment.start) during rendering:
```
appointments.map((appointment) => {
if (appointment.start < startOfToday) {
appointment.start = startOfToday; // <= mutates reactive state!
}
});
```
And `startOfToday` is set by
`DateTime.now().set({ hours: 0, minutes: 0, seconds: 0 })`
Which doesn't zero milliseconds, so each render creates a new
`startOfToday` with a later millisecond value.
The comparison `appointment.start < startOfToday` keeps being true
triggers another write => another re-render => infinite loop.
Forward-Port-Of: odoo/enterprise#109915This update fixes a bug related to member removal confirmation messages and ensures that actions related to archived users are restricted. This improves the user experience and prevents unintended actions when users are no longer active.
Original PR description
*=im_livechat, test_discuss_full Purpose the commit: - To update the string the member removal confirmation dialog. - Restrict the actions usage for archived users. task-5944930 part of-5867464
This update resolves an issue where calls within Discuss were failing due to race conditions with initial channel data fetching. The fix ensures that all necessary channel information is fully loaded before initiating calls, preventing outdated data from causing problems. This improves the stability and reliability of the Discuss call feature.
Original PR description
...in crosstab call test The "join/leave sounds are only played on main tab" test could race with the initial `channels_as_member` fetches triggered when opening Discuss in both tab Those fetches return full channel data, including `rtc_session_ids`. one of their responses could arive after the call had already progressed or ended and overwrite the state with stale RTC data Wait for `channels_as_member` to be fully processed after opening Discuss in each tab before starting the call. fix for: https://runbot.odoo.com/odoo/runbot.build.error/241061
This update resolves an issue where large file uploads to forms would fail, resulting in error messages. The fix adjusts how the system handles request sizes, ensuring compatibility with our web server's limits. This prevents form saving failures and improves the user experience when uploading files.
Original PR description
# How to reproduce - A reverse proxy needs to be set up between the client and the backend (for localhost, you can use nginx) - This reverse proxy needs to have a request max body size set below…
# How to reproduce - A reverse proxy needs to be set up between the client and the backend (for localhost, you can use nginx) - This reverse proxy needs to have a request max body size set below 128mb (for nginx : client_max_body_size) - If the system parameter web.max_file_upload_size is set, delete it and refresh your page - Pick any form view and add a file field with studio - Upload a file larger than the limit set in the proxy, but smaller than 128mb - Save the form # The problem The form is not saved and depending on the version, a Traceback will be shown (18.X) or a Connection Lost notification will be shown for a short period of time (19.0+) # Why When the system parameter web.max_file_upload_size is not set, the check for file size uses the default 128mb. A binary field added to a form via studio will upload its file in the json of the post request. This is done by encoding the file in base64. Our nginx servers set a limit for the request body size (usually 64mb). So if you add a file between 64mb and 128mb, it will bypass the default front-end size check but be stopped by the nginx reverse proxy. The proxy will send back an HTTP response with error code 413 to the client. Theses http responses are not correctly handled by the framework and are interpreted as a Connection Lost error because the response content cannot be parsed to json. Additionally, since we use base64 for the encoding and then use gzip to compress the json request, it's not really feasible to synchronize the front-end limit with the nginx one. opw-5891662 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252325 Forward-Port-Of: odoo/odoo#249025
This update resolves an issue where the Gantt view for service projects would produce an error when grouping by project. The fix adjusts how date comparisons are handled within the task domain, ensuring compatibility with dynamic date formats used in the system. This improves the stability and usability of the Gantt view.
Original PR description
### Issue: When in the Gantt view of service projects, grouping by project results in a traceback. ### Steps to reproduce: - Create another field service project - Create a task in the new project…
### Issue: When in the Gantt view of service projects, grouping by project results in a traceback. ### Steps to reproduce: - Create another field service project - Create a task in the new project and add start and end dates - Go to Field service > my tasks > gantt view > group by project - Error with traceback `time data 'today' does not match format '%Y-%m-%d %H:%M:%S'` ### Cause: This [commit](https://github.com/odoo/odoo/commit/d1ea43f6721116914762ea323d8a5987f043e87f) added the possibility to use dynamic dates in domains. Then all domains were changed in 42b1fca8e127926a06f503d79c8baeddf7d5ae82 But `_expand_domain_dates()` is trying to parse the dates as if they were written in ISO format: https://github.com/odoo/enterprise/blob/be853cc1ee544dda580960d94417cfdff2c8a7db/project_enterprise/models/project_task.py#L626 ### Solution: We use the method `parse_date()`, which was added with dynamic dates, to parse them. opw-5955317 Forward-Port-Of: odoo/enterprise#109236
This update fixes an issue where new timesheets weren't correctly selecting the appropriate Service Order Line (SOL) when creating timesheets in a multi-company setup. Now, the system automatically links the user's billing rates to the correct SOL, ensuring accurate billing calculations regardless of the company being used.
Original PR description
****Behavior:**** **Current:** In a multi company environment, when a sale contains multiple tasks in some project, and the user has billing rates indicating they should be assigned to a specific…
****Behavior:**** **Current:** In a multi company environment, when a sale contains multiple tasks in some project, and the user has billing rates indicating they should be assigned to a specific task, creating a new timesheet for the project does not set the correct SOL. This only happens if the sale is happening from a company that does not have an employee linked to the user. **Expected:** The new timesheet should be able to connect the current user to the related employee in the billing rates to find the right SOL. In the situation in which multiple companies have created an employee for the same user, and more than one of these has been linked to a SOL in the billing rates (unlikely workflow): We choose the SOL linked to the employee record created for the currently activated company, otherwise, we default to the first employee in the list. **Steps to reproduce:** - Be in a multicompany environment: company A and B - Create User with access to both but only one employee record for company A - Switch to company B - Create 2 services product, both creating a task in the same project. - Activate Billable Rate Indicators in the settings - Create a quote with both services and confirm - Go to the related project, and in the Invoicing tab, link employee from company A to SOL2 - As the user, check both companies but set company B as current active - Go to timesheet and create a new timesheet, when setting the project from the quote, you should see SOL1 by default, however we would want SOL2 as it was configured. opw-5159195 Forward-Port-Of: odoo/odoo#234200
This update fixes an issue where instructions added to Work Orders weren't properly linked when creating Purchase Orders via the mobile app. The fix restores a key data field, allowing instructions from the Bill of Materials to be correctly associated with the Purchase Order. This ensures accurate order fulfillment on the shop floor.
Original PR description
# How to reproduce - Create a BOM for a product with a Work Order - Add instructions to the WO - Using mobile, create a new MO for the product # The problem The instructions are not linked to the MO. This can easily be seen via the shop floor application # Why This issue is identical to https://github.com/odoo/odoo/pull/197889. This commit https://github.com/odoo/odoo/commit/b1ceec4c616d8ad2fee5b0fa1ce76c85cacbb344 removed the operation_id field from the workorder kanban mobile view, which is used in the MO form on mobile. operation_id is then not passed to the server in vals_list when creating the MO but it is required to link the instructions from the BOM to the MO. opw-5950983 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#250090
This update resolves an issue where database upgrades from 19.0 to 19.1 were failing due to an incorrect version comparison. The fix removes a misleading prefix from version comparisons, ensuring upgrades work as expected and settings are correctly applied. This prevents users from encountering unexpected configuration changes after upgrading.
Original PR description
Before this commit, upgrade of local storage from 19.0 to 19.1 were not working. Steps to reproduce: - have DB in 19.0 with message sound "off" in Discuss Notifications settings - upgrade to 19.1 DB (or make a fresh 19.1 DB on same sub-domain) - log on this new DB => "message sound" settings is "on" when it should be "off". This happens because the server version is "saas~19.1" and the prefix `saas~` was not taken into account. As a result, the version `saas~19.1` was mistakenly considered as lower than `19.0`. This commit fixes the issue by omitting the prefix `saas~` in the utils function of version comparison, which is what is used by the local storage internal code to compare versions. Upgrade version has been bumped to `19.1.1` and upgrade scripts have their sub-version explicitly set to `19.1.0`, so that these scripts are run for versions equal or lower than `19.1.0`, meaning they re-run also for `19.1.0`. Task-6008166
This update resolves an issue preventing PDF export of composite reports containing journal report sections. The fix ensures that journal reports utilize their specialized PDF generation process, correctly formatting data for accurate PDF output. This improves the functionality of composite reports for users generating financial reports.
Original PR description
# Steps to reproduce: * Enable **Developer Mode**. * Go to **Accounting → Configuration → Accounting → Accounting Reports**. * Create a new report and enable **Composite Report**. * Add a new line of…
# Steps to reproduce: * Enable **Developer Mode**. * Go to **Accounting → Configuration → Accounting → Accounting Reports**. * Create a new report and enable **Composite Report**. * Add a new line of type **Journal Report**. * Save the report and create a menu item from the gear icon. * Open the report from the reporting menu. * Try to download the report in **PDF** format. # Observed behavior: * PDF export fails with a traceback. * Composite reports containing journal report sections cannot be exported as PDF. # Cause When exporting a composite report to PDF, the export flow iterates over each embedded sub-report and generates the HTML body used for PDF rendering. * The composite export relies on the base [`export_to_pdf`](https://github.com/odoo/enterprise/blob/a4e2c7c7d3aa50c8b57668c9ca73f523a31a5c41/account_reports/models/account_report.py#L5875) implementation from `account.report`, which directly calls `_get_pdf_export_html()` for each sub-report. * For standard reports, this works as expected because they use the base [`_get_pdf_export_html`](https://github.com/odoo/enterprise/blob/a4e2c7c7d3aa50c8b57668c9ca73f523a31a5c41/account_reports/models/account_report.py#L5944) method, which renders flat report lines into the default PDF template. * Journal reports, however, rely on a completely different PDF structure. Their templates expect `document_data` (journal entries grouped by journal/document) instead of flat report lines. * This `document_data` is generated exclusively by the journal report’s custom handler via its own [`export_to_pdf`](https://github.com/odoo/enterprise/blob/a4e2c7c7d3aa50c8b57668c9ca73f523a31a5c41/account_reports/models/account_journal_report.py#L240) flow. * The handler builds the required `document_data` using [`_generate_document_data_for_export`](https://github.com/odoo/enterprise/blob/a4e2c7c7d3aa50c8b57668c9ca73f523a31a5c41/account_reports/models/account_journal_report.py#L261C9-L261C22). * When a journal report is embedded inside a composite report, the composite export logic bypasses the custom handler and forces the report through the base `_get_pdf_export_html()` pipeline. * Since the base pipeline does not generate `document_data`, the journal report PDF template fails at render time with `KeyError: 'document_data'`. In short, journal reports embedded in composite reports were incorrectly routed through the standard PDF export pipeline instead of their specialized handler-based one. # Fix: * Add PDF export support to the journal report custom handler. * Centralize common print option logic in a shared helper. * Update composite report export logic to delegate PDF generation to custom handlers when available. * Journal reports inside composite reports now export to PDF correctly. opw-5477551 Forward-Port-Of: odoo/enterprise#109790 Forward-Port-Of: odoo/enterprise#105040
This update ensures that late hours reporting only considers attendance records for employees based in Saudi Arabia. Previously, the system incorrectly processed attendance data from other countries, leading to inaccurate reporting. This change improves the accuracy of late hours calculations specifically for our Saudi Arabian clients.
Original PR description
Before this fix, the `_compute_l10n_sa_late_hours_visible` method was processing all attendance records regardless of the employee's company country. This caused issues for non-Saudi companies. Changes: - Filter attendance records to only process employees from Saudi Arabian companies (country_code == 'SA') - Set `l10n_sa_late_hours_visible` to False for non-SA attendances - Add `employee_id.company_id.country_id` to the compute dependencies - Add `string` attribute to `l10n_sa_expected_check_in` field - Add test case to verify late hours visibility is country-specific task-5491785
This update fixes an issue where manually refunding products through the POS (using negative quantities) resulted in invoices instead of credit notes. The fix ensures that manual refunds are correctly processed as credit notes, streamlining the accounting process for refunds without using the standard refund workflow. This improves accuracy and simplifies reconciliation.
Original PR description
Creating a POS order with negative quantity to manually refund a product (without using the Refund action, e.g. when the original order is not in the POS) and then requesting an invoice produced a…
Creating a POS order with negative quantity to manually refund a product (without using the Refund action, e.g. when the original order is not in the POS) and then requesting an invoice produced a customer invoice (INV) instead of a credit note (RINV). Steps to reproduce: ------------------- * Open a POS session. * Create a new order (do not use "Refund" from an existing order). * Add a product with negative quantity to simulate a manual refund. * Set a customer and request an invoice for the order. * Pay the order (negative amount). > Observation: The system creates a customer invoice (INV) instead of a credit note (RINV). Why the fix: ------------ * Invoice type was decided only from the `is_refund` flag, which is set only when the order is created via the Refund action. Manual refunds (negative qty) never had `is_refund` set, so they were treated as sales and got `out_invoice`. * `_prepare_invoice_vals` now treats an order as a refund when `is_refund` is True or `amount_total < 0`, so `move_type` is `out_refund` for manual refunds and a RINV is created. * `_get_invoice_lines_values` now uses the same condition (`is_refund or amount_total < 0`) to compute `is_refund_order` for the quantity sign. That way invoice lines keep positive quantities and the credit note has a positive total. opw-5898700 Forward-Port-Of: odoo/odoo#248791
This update fixes an issue where stock accruals were incorrectly calculating amounts when the 'stock' module wasn't installed. It now correctly handles stock variations and ensures accrual lines are generated separately for each sale order line, providing more accurate financial reporting. This improves the reliability of our accounting processes.
Original PR description
### [FIX] (stock_)account: cost method
> Before this commit, we tried to access to `product.product` `cost_method` field in `account` module.
> The issue is: this field is defined in `stock_account` which means we can try to read an unexisting field if we try to generate accruals from a sale order or a purchase order without `stock` installed.
>
> This commit creates an helper method, overrided in `stock_account`, to avoid this issue.
### [FIX] account: split stock variation accrual lines
> Before this commit, accrual lines created for stock variations in case of already incoived not delivered quantities were summed together.
> This commit keeps them separate: one line by sale order line.
>
> Also, those lines' label is rewritten to be more specific, giving the amount of invoiced and delivered qties, and with what unit price.
task-5934232
Forward-Port-Of: odoo/odoo#250408This update fixes an error in how project budgets are calculated, ensuring accurate spending and remaining amounts. Previously, the system was displaying incorrect percentages and signs due to a double-negation issue. Now, the budget summary correctly reflects the actual spending against the planned budget.
Original PR description
Steps to reproduce: --------------------------- 1. Install the `project_account_budget` and `account_accountant` modules. 2. Create a new project and add an Analytic Account for it from the settings…
Steps to reproduce: --------------------------- 1. Install the `project_account_budget` and `account_accountant` modules. 2. Create a new project and add an Analytic Account for it from the settings page 3. Open the Project Kanban, click the three dots on the project card, and select Project's Updates. 4. Click Add Budget button and open the budget wizard. 5. Add a budget line in the wizard with a planned amount expressed as a negative value for an expense (for example: -10000). 6. Create a Vendor Bill using the same analytic account with an amount of 1000. 5. Confirm the bill. 6. Go back to Project's Updates and click New button to view the budget summary. Observation: --------------------------- The budget summary displays incorrect signs and percentages in Activities summary, for example: ``` -10.0% (-1,000.00) of the -10,000.00 budget has been spent. 110.0% (-11,000.00) of the budget is remaining. ``` This incorrectly shows -10% spent and 110% remaining instead of 10% spent and 90% remaining (-9,000). Issue: --------------------------- The project cost (already negative) was negated again when computing the spent amount in https://github.com/odoo/enterprise/blob/ac3f333d97eda5c86a0813490ac6204d4ec5721f/project_account_budget/models/project_update.py#L16 Double-negating the cost makes it positive, which then gets added to the expense budget instead of reducing it, producing inverted percentages and signs. Solution: --------------------------- For expense budgets (negative budgets), do not apply an extra negative sign when calculating the project cost so the spent, remaining, and percentage values are computed correctly. After the fix: ``` 10.0% ($ 1,000.00) of the $ -10,000.00 budget has been spent. 90.0% ($ -9,000.00) of the budget is remaining. ``` opw-5357854 Forward-Port-Of: odoo/enterprise#109880 Forward-Port-Of: odoo/enterprise#102126
This update resolves a problem where Razorpay payments failed due to customer names containing commas or exceeding 50 characters. The fix ensures Razorpay receives only clean names (without commas) and limits them to 50 characters, preventing payment errors and improving the reliability of Razorpay transactions.
Original PR description
Steps: - Install and set up Razropay. - Create order and set customer with long name or name with comma. - Try to pay with Razorpay. Issue: - Error name is invalid. Cause: - Razorpay only take name without comma and upto 50 character, so having longer name or name with comma would cause an issue. Fix: - Replace comma with empty space and only take first 50 character of name while creating customer in Razorpay. Forward-Port-Of: odoo/odoo#252444
This update ensures that orders using certain online payment providers require a registered customer with an email address, resolving a 'Signature mismatch' error. This change aligns with provider requirements and prevents payment failures when a customer isn't associated with the order, improving payment processing reliability.
Original PR description
Currently some providers require a customer to be registered on the order because the email address needs to be sent with the request. We the order does not have a customer the payment cannot be made…
Currently some providers require a customer to be registered on the order because the email address needs to be sent with the request. We the order does not have a customer the payment cannot be made using that provider. Step to reproduce: ------------------ - Set up Amazon payment services on a online pos payment method - Set this method as the online payment method for a self and also set is as payment method of the pos - Place an order in the self or without a customer on the normal pos - Try to pay it > Observation: When the page is redirected to provider's checkout page, an error occurs: Signature mismatch Why the fix: ------------ On a normal pos shop we are simply ensuring that a customer with an address mail is registered on the order if the provider of an online payment method requires customer identification. - When selecting the payment method on the payment screen if the payment method is online, requires customer identification and there's no customer on the order, the validate order button will be unavailable and the customer button is highlighted. - When there is a customer the validate button is highlighted - When validating the order if the customer does not have an email it will not go through and warn the cashier that the customer needs an email. This behavior is similar to the present "Delivery" which, if the cashier disregarded all popups, will not have the validate button available until a cashier is registered. Also if the selected customer doesn't have an address it will show a popup upon validation. We are not doing anything regarding the self order as using presets like "Delivery" is compatible since the information required filled by the customer creates a partner in the db and sets it on the order. This preset ensures we always have a partner. Other preset don't but we don't want to block flows that are currently working. The list of providers requiring customer identification can be extended. opw-5406501 Forward-Port-Of: odoo/odoo#245016
This update resolves a visual issue where list views with search panels (like Rental or Employees) would sometimes display a horizontal scroll bar. This change ensures that list views with search panels display data correctly on mobile devices, providing a consistent and usable experience for users. The fix was implemented to improve the overall user experience and prevent data from being hidden.
Original PR description
This PR aims to fix the horizontal scroll overflow which only affects list views with a search panel (e.g. Rental, Employees, etc.). task-5888678 | Before | After | |--------|--------| | <img width="1125" height="2436" alt="Screen Shot 2026-02-19 at 15 29 15" src="https://github.com/user-attachments/assets/b89d2979-78a8-4c58-8f7f-7dedb6fc8fff" /> | <img width="1125" height="2436" alt="Screen Shot 2026-02-19 at 15 30 10" src="https://github.com/user-attachments/assets/0989b6e7-ef91-43b5-8df5-c27696d43f65" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249506
This update fixes a bug where POS sessions weren't correctly calculating and posting COGS when using 'real-time' product valuation. The change ensures COGS are accurately recorded regardless of the valuation setting, resolving a potential issue with inventory accounting. This improves the reliability of POS financial reporting.
Original PR description
When the product category valuation is set to `real_time` but the company is set to `periodic`, the POS session closing was not posting COGS entries as expected. If the product category valuation is…
When the product category valuation is set to `real_time` but the company is set to `periodic`, the POS session closing was not posting COGS entries as expected. If the product category valuation is set to `real_time`, it should always prevail over the company setting. And if no valuation is set on the product category, then the company setting should be used. Steps to reproduce: ------------------- * Create a product category with `Inventory Valuation` set to `real_time` (Perpetual). * Create a product in this category and make sure it is storable and has a cost price. * Set the company `Inventory Valuation` to `periodic` (Periodic). * Create a POS order with this product and pay it. * Close the POS session. > Observation: In the session no COGS entries are created for the sold product. Why the fix: ------------ We adapt the `_search_valuation` to correctly fallback on the company setting only if the product category valuation is not set. It was not working before because in some cases the product had no company set (it means that it is visible to all companies) and the domain was not matching. To fix that we check that the current company matches the search value, and if it does we also match all the products without company set. We also adapt the PoS code to use the `product_id.valuation` field to filter all the stock_moves that should create COGS entries when closing the session. opw-5885960 Forward-Port-Of: odoo/odoo#247011
This update optimizes the Point of Sale (POS) system to significantly reduce memory consumption, particularly when handling large product catalogs. The changes result in a substantial decrease in memory usage across Chrome, Safari, and Firefox, leading to a smoother and more responsive POS experience.
Original PR description
This commit reduces memory consumption in the POS, especially when loading a large number of products. Reactivity usage has been optimized, particularly for product data. Additional optimizations were implemented to handle large product sets more efficiently. Metrics 5,000 products • Chrome: 440 MB → 75 MB • Safari / Firefox: 1 GB → 250 MB 20,000 products • Chrome: 1.5 GB → 135 MB • Safari / Firefox: 4 GB → 300 MB Enterprise PR: https://github.com/odoo/enterprise/pull/107978 Forward-Port-Of: odoo/odoo#249542
This update optimizes the Point of Sale system to use less memory, particularly when handling a large number of products. The changes result in significantly reduced memory consumption across browsers, leading to a smoother and more responsive user experience for our retail customers.
Original PR description
This commit reduces memory consumption in the POS, especially when loading a large number of products. Reactivity usage has been optimized, particularly for product data. Additional optimizations were implemented to handle large product sets more efficiently. Metrics 5,000 products • Chrome: 440 MB → 75 MB • Safari / Firefox: 1 GB → 250 MB 20,000 products • Chrome: 1.5 GB → 135 MB • Safari / Firefox: 4 GB → 300 MB Community PR: https://github.com/odoo/odoo/pull/249542 Forward-Port-Of: odoo/enterprise#107978
This update ensures that customers receive receipt emails only after their online self-order payment has been successfully validated. Previously, emails were sent prematurely, potentially confusing customers about the status of their order. This change improves the customer experience by aligning receipt notifications with actual payment success.
Original PR description
In self-order with online payment, the receipt email could be sent when the order was created (before payment validation), which confirms the order too early for customers. This change ensures receipt sending is aligned with actual payment success in the online self-order payment flow. Steps to reproduce: ------------------- * Configure self-order with a preset that has a receipt mail template. * Place a non-zero self-order using online payment and reach the payment step. * Check customer mailbox before validating payment. > Observation: A confirmation email can be sent before the payment is confirmed. Why the fix: ------------ Receipt emails must reflect a successful payment outcome, not just draft order creation. The online self-order payment success path now triggers receipt sending after the order transitions from draft to paid/done, preventing premature emails. opw-5938299 Forward-Port-Of: odoo/odoo#251220
This update fixes an issue where part-time employees were incorrectly displaying their maximum weekly hours. The system now accurately uses the employee's defined 'hours_per_week' as the limit, ensuring accurate hour calculations and display in the employee's schedule. This improves the scheduling accuracy for flexible staff.
Original PR description
### Issue: When having a part-time flexible employee (`hours_per_week` < `full_time_required_hours`), some values still show `full_time_required_hours` as the total hours they should work in a week.…
### Issue:
When having a part-time flexible employee (`hours_per_week` < `full_time_required_hours`), some values still show `full_time_required_hours` as the total hours they should work in a week.
Steps to reproduce:
- Have an employee with a part-time flexible schedule
- `full_time_required_hours`: 40
- `hours_per_week`: 24
- `hours_per_day`: 8
- Go in Attendances
- Hover the employee
- It shows ...h/40h but it should show ...h/24h
Cause:
In `_attendance_intervals_batch()` we build theoretical attendances for flexible employees. Starting at the start of the week, we add an attendance of `hours_per_day` each day until we reached `full_time_required_hours`.
In the case above, we would return five attendances of 8h, ignoring `hours_per_week`.
Then `_get_attendance_intervals_days_data()` counts the hours to display them in the Gantt view.
Solution:
In `_attendance_intervals_batch()` we use `hours_per_week` instead of `full_time_required_hours` as the weekly limit of hours per week.
A lot of tests needed to be adapted, as they were specifying `full_time_required_hours` but not `hours_per_week` when creating calendars.
opw-5973117
Forward-Port-Of: odoo/enterprise#109645This update resolves an issue preventing users from replying to messages received from other companies within Odoo. Previously, attempts to respond resulted in an error. Now, replies are correctly logged when the user has access to the company from which the message originated, improving communication across multiple businesses.
Original PR description
Before these changes, messages from other companies were received, but when trying to reply to them, an error occurred that prevented the response. Steps to reproduce the issue in runbot: 1. In one tab, log in as admin, and in another incognito tab, open demo. 2. Make sure demo has Handle Notifications in Odoo enabled. 3. Set admin in one company and demo in another company. 4. Assign a task to demo. 5. Click on the notification to open the chatter and try to reply. An error is thrown With these changes, the response can be logged when the user has access to the company from which the task was assigned. cc @Tecnativa TT61176 ping @pedrobaeza --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251555 Forward-Port-Of: odoo/odoo#250677