Monday, September 22, 2025
12 changes · saas-18.3
Enhancements to existing features
Australian payroll calculations have been updated to follow the latest ATO Schedule 8 student and training support loan withholding rates. This helps businesses apply the correct withholding for eligible employees from the September 2025 update period and stay aligned with ATO guidance.
Original PR description
This commit updates the Schedule 8 witholding flow and rate for mid year update as per ATO guidelines effective from 24-09-2024. https://softwaredevelopers.ato.gov.au/2025-pay-you-go-payg-withholding-tax-tables Task: 5088270 Forward-Port-Of: odoo/enterprise#95083
Resolved issues and error corrections
Odoo now blocks invalid custom view changes before they can be saved. This prevents Web Studio from failing to open when a malformed customization is entered through technical settings, reducing disruption for users managing forms.
Original PR description
This error occurs when a user modifies a Studio-generated custom form view by updating it through the technical settings and adds an invalid XPath expression. As a result, Web Studio fails to open and load the view. **Steps to replicate:** * Install `contacts` and `web_studio` * Open form view for any contact and Add/remove any field using studio. * Go to technical>User Interface>Views> `Odoo Studio:res.partner.form customization` * Add the following line:`<xpath expr='/form[1]/field[6]'/>` inside data and save. * Go to contact form view and open studio. `ValueError:The element <xpath expr='/form[1]/field[6]'/> cannot be located in the main view` **Solution** * Prevent users from saving changes to a view by raising a validation error when an invalid XPath expression is detected. **Sentry-6678221213**
This fixes an issue where Saudi Arabia invoice PDFs could print without the company logo when certain localization modules were installed together. Businesses using Saudi invoicing get properly branded customer invoices again, improving document presentation and consistency.
Original PR description
steps to reproduce: ------------------- 1. Install `l10n_sa_edi` and `l10n_latam_invoice_document` 2. Create and confirm an invoice. 3. Print the invoice PDF issue: ------ The company logo is not…
steps to reproduce:
-------------------
1. Install `l10n_sa_edi` and `l10n_latam_invoice_document`
2. Create and confirm an invoice.
3. Print the invoice PDF
issue:
------
The company logo is not printed on the invoice PDF.
cause of the issue:
-------------------
The `l10n_latam_invoice_document` hides the standard company logo if
`company_header` is set to true:
https://github.com/odoo/odoo/blob/0f6cb037e05db86e808682659a12442464b2cdd2/addons/l10n_latam_invoice_document/views/report_templates.xml#L6-L8
In the case of `l10n_sa`, the custom_header value is set because of this condition:
https://github.com/odoo/odoo/blob/0f6cb037e05db86e808682659a12442464b2cdd2/addons/l10n_sa/views/report_invoice.xml#L23
However, the condition in `l10n_latam_invoice_documnet` expects
a callable record instead of static XML data, which is incorrect:
https://github.com/odoo/odoo/blob/022fcbcf40a28afa56010f6130c26bb0503d5467/addons/l10n_latam_invoice_document/views/report_templates.xml#L9-L14
solution:
---------
Renaming the variable to `custom_header_sa` resolves the issue.
<details>
<summary>Click here to see:</summary>
Before:
<img src="https://github.com/user-attachments/assets/f4606a44-10ce-4038-92a3-2c8ec2a69edf"/>
After:
<img src="https://github.com/user-attachments/assets/70055155-63f2-4fec-aaf6-3bf5587f5591"/>
</details>
opw-4977422
Forward-Port-Of: odoo/odoo#225476Bus notifications now include both direct and inherited user groups when deciding who should receive real-time updates. This ensures administrators and other users with implied group access see new auto-subscribed Discuss channels immediately without needing to reload.
Original PR description
To target users of a group, bus notifications are sent on group records. To do so, user groups are added to its bus subscription. However, since odoo/odoo#179354, only explicit groups are added, not every implied group. It's incorrect. For example, sending on the user channel doesn't notify administrators while it should. Steps to reproduce (note that the steps are only working for admin): - Click the gear button on the sidebar in discuss page to navigate to the channel kanban view as admin - Click the `New` button and create a channel with an internal users group as `Auto Subscribe Groups` - Go back to the discuss main page. The new channel will not be pinned unless you reload the page See: https://github.com/odoo/odoo/pull/179354/files#r1954163704 Forward-Port-Of: odoo/odoo#217543
Duplicate detection now ignores company differences when a database only has one company. This lets users find and merge duplicate records that were previously missed, improving data cleanup accuracy.
Original PR description
**Issue** In single company databases, it wasn't possible to find duplicate records with different `company_id` values to merge them (in multi company databases, it is possible to enable the "Cross-Company" option on the deduplication rule). **Change** Always ignore the company field in single company databases. opw-4794408 Forward-Port-Of: odoo/enterprise#94797 Forward-Port-Of: odoo/enterprise#93184
This fix prevents certain Spanish balance sheet accounts from being counted twice in the “Other current payables” section. As a result, companies using the Spanish SME balance sheet report will see more accurate liability totals that better match their accounting records.
Original PR description
In **`balance_pymes_line_32300`** (`CURRENT LIABILITIES > Current payables > Other current payables`), amounts are **doubled** because account **551** is included twice. * **Formula using…
In **`balance_pymes_line_32300`** (`CURRENT LIABILITIES > Current payables > Other current payables`), amounts are **doubled** because account **551** is included twice.
* **Formula using `account_codes`:**
```xml <field name="formula">-1034 - 1044 - 190 - 192 - 194 - 500 - 501 - 505 ...551 - 5566 - 5595 - 5598 - 560 - 561 - 569</field> ```
→ Explicitly includes account **551**.
* **Formula using `domain`:**
```xml <field name="formula" eval="['|', ('account_id.code','=like','550%'), '|', ('account_id.code','=like','551%'), '|', ('account_id.code','=like','554%'), ('account_id.code','=like','5525%')]"/> ```
→ Includes **all accounts starting with 551**, so **551** is also counted here.
This overlap causes the balance to be counted twice, inflating the reported value.
**steps to reproduce:**
1. With a Spanish company, go to **Accounting > Dashboard > Bank > Transaction > New**.
2. Select an account, search for **55100**, and add it.
3. Go to **Reporting > Balance Sheet > Other current payables**.
4. Notice that the reported amount is **double** the actual accounting data.
Overlapping formulas: specific account `551` and `5525` are counted in `account_codes`, while the `domain` formula already includes `551%`, leading to duplication.
**Fix**
Remove explicit account codes from `account_codes` if they are already covered by the `domain` prefixes to avoid double-counting. and also made sure to correct the same issue in the whole report.
opw-5075035Fixed an issue where importing spreadsheets could fail when text fields contained values that looked like dates, or when related date fields were used. This makes XLSX imports more reliable for records such as pricelists, product data, and names that may resemble dates.
Original PR description
*: test_import_export ### Steps to reproduce: - Go to Sales/Prodcuts/Pricelists - Create a new pricelist with a rule with a set Valid Period - Export that record adding the Pricelist Rule/Start Date…
*: test_import_export ### Steps to reproduce: - Go to Sales/Prodcuts/Pricelists - Create a new pricelist with a rule with a set Valid Period - Export that record adding the Pricelist Rule/Start Date (item_ids/date_start) as XLSX format - Delete the record and test the import the XLSX file #### Uncaught Promise: > Invalid props for component 'ImportDataColumnError' :'resultNames' is undefined (should be a array) ### Cause of the Issue: The issue is raised by the error message: https://github.com/odoo/odoo/blob/32bdff8bc603a03038d3f9e38463809883319305/addons/base_import/models/base_import.py#L1428-L1432 which is not properly handled by the `ImportDataColumnError` component. However, in the present situation, the issue is just that this error message itself should not be raised in the first place. #### Details: Since commit 630b2683d3aad203b0bbf7d2d63b88cd4d3bd9d7, date and datetime formatted cells in spreadsheets are no longer Char field. Instead, they are imported as date and datetime objects. This was intended to allow importing columns with mixed encodings (e.g., some values stored as strings, others as dates in the spreadsheet). However, a side effect of this change is that if a char-type field contains values that a spreadsheet interprets as dates or datetimes, the import fails. For example, an account move name "21/12/2025" may be interpreted as a date. Attempting to perform a join on this string expected value causes a traceback here: https://github.com/odoo/odoo/blob/32bdff8bc603a03038d3f9e38463809883319305/addons/base_import/models/base_import.py#L1628-L1632 To address this discrepancy, commit 91dca74b3e395c8ee410db18784990ba3a6a7e6e introduced a check raising an error if the imported field type is not appropriate to carry a `date/datetime` value. This fix has two major issues: 1) It still does not handle the above use case correctly—it remains impossible to import "21/12/2025" as a record name. 2) (The present issue) It does not properly check the type of related fields. For example, a field like "company_id/partner_id/membership_start" is not considered as an allowed date field. The current check on allowed date fields being overly simplistic: https://github.com/odoo/odoo/blob/32bdff8bc603a03038d3f9e38463809883319305/addons/base_import/models/base_import.py#L1416-L1421 ### Fix: We propose reverting commit 91dca74b3e395c8ee410db18784990ba3a6a7e6e. And instead of recursively computing the related model and the appropriate types of related fields (including property-type relational fields), we will simply stringify values when they are written into char-like fields (e.g., char or text). Note: this may also require an adjustment in master for the html type. opw-4935423 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226807
Payroll users with Administrator access can now cancel payslips that are marked as done, as intended. This fixes an incorrect permission check that previously blocked authorized payroll administrators unless they were full system admins.
Original PR description
steps to reproduce: ------------------- 1. Install payroll 2. Create a user and grant "Administrator" access to Payroll. 3. Log in as the new user and try to cancel a 'Done' payslip. issue: ------ A UserError is raised: "Cannot cancel a payslip that is done." observation: ------------ A user with Payroll "Administrator" access is unable to cancel a payroll payslip cause of the issue: ------------------- During cancellation, the system checks whether the user is "Admin" instead of verifying if the user has Payroll "Administrator" access. https://github.com/odoo/enterprise/blob/13832d80570956e504e1c09f41acbeb0bc4baedc/hr_payroll/models/hr_payslip.py#L509-L513 solution: ---------- Check that the user has Payroll "Administrator" access. opw-5040029 Forward-Port-Of: odoo/enterprise#95049 Forward-Port-Of: odoo/enterprise#93831
Date filters in timesheet forecast reports now respect each user's local timezone more accurately. This prevents records from being incorrectly included or excluded by one day for users in timezones far from UTC, improving report reliability.
Original PR description
This commit fixes the timezone issues with the Date filters, in which we were comparing a UTC DateTime value to a local timezone's Date. In certain timezones, this leads to off-by-one errors in the records fetched from the DB, depending on how far ahead or behind UTC that timezone is. Specifically, we remove the UTC conversion within the filter domains. opw-5068870 Forward-Port-Of: odoo/enterprise#94032
Timesheet and attendance reports now match entries against the user's local date instead of UTC time. This prevents “Today,” “This Week,” and “Last Week” filters from showing the wrong day for users in certain time zones.
Original PR description
This commit fixes issues with the timesheet Date filters, in which the `date` field of account.analytic.line records, which is stored as the local timezone's date, is being compared to a UTC DateTime value. This leads to off-by-one errors. For example, if you are in Berlin and try to filter for all timesheet entries from "Today", you will only find entries from the previous day. Similarly, for the "This Week" and "Last Week" filters, which would be shifted by one day. The filter domains have been changed to compare the `date` to the local timezone's "today". opw-5003310 Forward-Port-Of: odoo/odoo#225753
This fix ensures online orders use the correct warehouse when a customer switches from Click and Collect to standard delivery before payment. It prevents quotations from incorrectly staying tied to the Click and Collect warehouse, improving order fulfillment accuracy.
Original PR description
Steps: - Activate Click and Collect, then create a new warehouse. - For the product, add quantities in both locations. - Assign the second warehouse to Click and Collect. - Go to the website, add the product to the cart, choose Click and Collect as the delivery method, then switch it to Delivery and confirm payment. Issue: - When checking the quotation, it still uses the warehouse linked to Click and Collect. Cause: - Warehouse recomputation logic is called after _remove_delivery_line which resets the delivery_type of sale order. Since delivery_type is reset the sale order filter for warehouse recomputation does not work as intended. Fix: - Moved warehouse recomputation logic to _set_delivery_method which will filter the sale order before _remove_delivery_line. opw - 4965726, 5004170 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225989
The Planning app now calculates weekly progress for flexible employees using only the part of a shift that falls within the displayed week. This prevents shifts spanning multiple weeks from overstating allocated hours, giving managers a more accurate view of weekly capacity.
Original PR description
### Steps to reproduce: - Install Planning app - Create a shift for a flexible employee that starts on Friday and end on the following Tuesday for example - Go to the gantt view for the week that the shift should start at - Notice the progress bar is showing the whole allocated hours not just the week's hours ### Cause: This mainly happening because when the employee is flexible we are getting the value by multiplying the hours_per_day of his schedule by the period.days and the period is the shift period ### Fix: We use the interval we are just checking as the period now so if the shift is extended to the next week we are just going to use the end of the week as the interval end not the shift's end_datetime opw-5022800 Forward-Port-Of: odoo/enterprise#93404