Wednesday, September 17, 2025
9 changes · saas-18.2
Resolved issues and error corrections
This fix prevents certain business-critical attachments from being moved to cloud storage when they are needed directly by Odoo processes, such as invoices or expense reports. It helps avoid issues where reports or business logic cannot access attachment data as expected.
Original PR description
some models use attachments for data for business logics for example, ``account_move.message_main_attachment_id.datas`` ``hr_expense_sheet`` will use all bounded attachments to generate report This commit prevents uploading attachments to cloud storage for some models if they ``_inherit`` or ``_inherits`` model ``mail.thread.main.attachment`` This PR is also a supplement for https://github.com/odoo/odoo/pull/226094 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227165
This fixes an accounting issue where taxes entered during bank reconciliation could be counted twice in cash basis tax reports. Businesses using cash basis taxes will now see more accurate tax amounts after reconciling bank or cash journal entries.
Original PR description
**Steps to reproduce:** - Install Accounting - In Accounting settings, activate "Cash Basis" - Create/modify a tax with "Tax Exigibility" set to "Based on Payment" - Set an account as "Cash Basis…
**Steps to reproduce:**
- Install Accounting
- In Accounting settings, activate "Cash Basis"
- Create/modify a tax with "Tax Exigibility" set to "Based on Payment"
- Set an account as "Cash Basis Transition Account"
- Create an invoice:
* Customer: [any]
* Invoice Lines:
- [Price] 200.0
- [Taxes] The cash basis tax (e.g. 15%)
- Confirm the invoice
- Go to "Bank" journal
- Create a bank statement for a lower amount than the invoice (e.g. $200)
- Match the statement with the invoice from the "Match Existing Entries" tab
- Select the added line and click on "fully paid" link
=> A new line with the amount difference should be added
- On the new line, select an expense account and the cash basis tax
=> A new tax line should be added (e.g. $3.91)
- Validate
- Go to "Accounting / Reporting / Statement Reports / Tax Report"
**Issue:**
The amount of the Tax is equal to:
[Tax amount of the invoice] - 2 * [Tax amount of the difference line] = $30 - 2 * $3.91 = $22.18
which is not correct.
The tax amount of the difference line (coming from the bank reconciliation widget) is taken twice into account.
**Cause:**
A cash basis move is created for the tax line created in the bank reconciliation widget.
This move is using the same tax account as debit and credit account and is directly reversed using the same account.
No cash basis move should be created for that line because the tax line is added while reconciling a bank statement, which means the tax should have been received.
**Solution:**
Do not create a cash basis move for journal entries made in a bank or cash journal.
opw-4663059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#227419
Forward-Port-Of: odoo/odoo#225151This fixes spreadsheet imports so values that look like dates can still be imported into text fields without causing errors. It helps users reliably re-import exported records such as pricelists or names that spreadsheet software may automatically format as 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
This fix changes how default purchase taxes are applied to large product catalogs, avoiding memory errors during accounting setup or upgrades. Businesses with many products sharing the same supplier tax can now complete the process more reliably.
Original PR description
As I mentioned in the query below, multiple grouped product.template records with the same supplier_taxes_id are being modified with the default purchase tax (account_purchase_tax_id),which leads to…
As I mentioned in the query below, multiple grouped product.template records with the same supplier_taxes_id are being modified with the default purchase tax (account_purchase_tax_id),which leads to a memory error. To prevent this, I have used an INSERT query.
```sql
SELECT tax_id, COUNT(*) AS product_count
FROM product_supplier_taxes_rel
GROUP BY tax_id
ORDER BY product_count DESC;
tax_id | product_count
--------+---------------
15 | 1262126
156 | 343332
114 | 36363
47 | 10132
23 | 202
546 | 11
474 | 5
782 | 2
666 | 2
1188 | 2
1318 | 1
3 | 1
(12 rows)
```
- Traceback
```python
Traceback (most recent call last):
File "/home/odoo/src/odoo/17.0/odoo/service/server.py", line 1314, in preload_registries
registry = Registry.new(dbname, update_module=update_module)
File "<decorator-gen-16>", line 2, in new
File "/home/odoo/src/odoo/17.0/odoo/tools/func.py", line 87, in locked
return func(inst, *args, **kwargs)
File "/home/odoo/src/odoo/17.0/odoo/modules/registry.py", line 110, in new
odoo.modules.load_modules(registry, force_demo, status, update_module)
File "/home/odoo/src/odoo/17.0/odoo/modules/loading.py", line 515, in load_modules
migrations.migrate_module(package, 'end')
File "/home/odoo/src/odoo/17.0/odoo/modules/migration.py", line 240, in migrate_module
migrate(self.cr, installed_version)
File "/home/odoo/src/odoo/17.0/addons/l10n_ch/migrations/11.3/end-migrate.py", line 8, in migrate
env["account.chart.template"].try_loading("ch", company)
File "/home/odoo/src/odoo/17.0/addons/account/models/chart_template.py", line 155, in try_loading
return self._load(template_code, company, install_demo)
File "/home/odoo/src/odoo/17.0/addons/point_of_sale/models/chart_template.py", line 22, in _load
result = super()._load(template_code, company, install_demo)
File "/home/odoo/src/odoo/17.0/addons/account/models/chart_template.py", line 214, in _load
self._post_load_data(template_code, company, template_data)
File "/home/odoo/src/enterprise/17.0/account_reports/models/chart_template.py", line 10, in _post_load_data
super()._post_load_data(template_code, company, template_data)
File "/home/odoo/src/odoo/17.0/addons/stock_account/models/account_chart_template.py", line 12, in _post_load_data
super()._post_load_data(template_code, company, template_data)
File "/home/odoo/src/odoo/17.0/addons/account/models/chart_template.py", line 669, in _post_load_data
sudoed_products_purchase._force_default_purchase_tax(company)
File "/home/odoo/src/odoo/17.0/addons/account/models/product.py", line 130, in _force_default_purchase_tax
product_grouped_by_tax.supplier_taxes_id += default_supplier_taxes
File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 1322, in __set__
records.write({self.name: write_value})
File "/home/odoo/src/odoo/17.0/addons/website_sale/models/product_template.py", line 176, in write
return super().write(vals)
File "/home/odoo/src/odoo/17.0/addons/rating/models/rating_mixin.py", line 100, in write
result = super(RatingMixin, self).write(values)
File "/home/odoo/src/odoo/17.0/addons/stock_account/models/product.py", line 55, in write
res = super(ProductTemplate, self).write(vals)
File "/home/odoo/src/odoo/17.0/addons/mrp/models/product.py", line 74, in write
return super().write(values)
File "/home/odoo/src/odoo/17.0/addons/stock/models/product.py", line 921, in write
return super(ProductTemplate, self).write(vals)
File "/home/odoo/src/odoo/17.0/addons/product/models/product_template.py", line 502, in write
res = super(ProductTemplate, self).write(vals)
File "/home/odoo/src/odoo/17.0/addons/mail/models/mail_thread.py", line 311, in write
return super(MailThread, self).write(values)
File "/home/odoo/src/odoo/17.0/addons/mail/models/mail_activity_mixin.py", line 250, in write
return super(MailActivityMixin, self).write(vals)
File "/home/odoo/src/odoo/17.0/addons/website/models/mixins.py", line 218, in write
return super(WebsitePublishedMixin, self).write(values)
File "/home/odoo/src/odoo/17.0/odoo/models.py", line 4444, in write
field.write(self, value)
File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 4337, in write
self.write_batch([(records, value)])
File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 4358, in write_batch
self.write_real(records_commands_list, create)
File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 4957, in write_real
y_to_xs[y].add(x)
File "/home/odoo/src/odoo/17.0/odoo/tools/misc.py", line 1136, in add
self._map[elem] = None
MemoryError
```
opw - 4544050
upg - 2459515
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#204931This fixes an error that could block users from recording timesheets on projects shared across multiple companies. Employees linked to the same user in different companies can now log time without being stopped by an incorrect company selection.
Original PR description
steps to reproduce: ------------------- 1. Install Employees, Timesheets, Projects 2. Create 2 companies 3. On each company, create an employee for the same related user 4. Create a project without…
steps to reproduce: ------------------- 1. Install Employees, Timesheets, Projects 2. Create 2 companies 3. On each company, create an employee for the same related user 4. Create a project without setting a company (making it a global project). 5. Enable both companies in the systray 6. Try to log a timesheet on the global project. issue: ------ A ValidationError is raised: "Timesheets must be created with an active employee in the selected companies." cause: ------ During `vals_list` preparation, the `company_id` value is overwritten here: https://github.com/odoo/odoo/blob/605e47a85561614c17fe2e6f59618610f87c69bb/addons/hr_timesheet/models/hr_timesheet.py#L381 If the project has no company set, `company_id `becomes **False**. This condition fails if the user has two employees and no company set (or if it is missing): https://github.com/odoo/odoo/blob/d3c7e51e94d98da9086a3817b157c4e125c80790/addons/hr_timesheet/models/hr_timesheet.py#L211-L215 solution: --------- Use `self.env.company` if company_id is missing(or False) in the vals. opw-4892449 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227268 Forward-Port-Of: odoo/odoo#223846
Vendor bill and expense sheet PDF reports now correctly fetch attachments stored as remote links or cloud resources before creating the report. This prevents report generation failures when supporting documents are not stored locally, improving reliability for users working with cloud-based files.
Original PR description
### Issue PDF reports fail when attachments are remote URLs or cloud storage resources. The `to_pdf_stream()` method expects local file data but receives boolean values from remote attachments,…
### Issue PDF reports fail when attachments are remote URLs or cloud storage resources. The `to_pdf_stream()` method expects local file data but receives boolean values from remote attachments, causing a TypeError. ### Solution Download remote resources before processing them in PDF reports. This ensures all attachments have accessible data regardless of storage type. ### Affected Reports - `account.report_original_vendor_bill` - Vendor bill reports - `hr_expense.report_expense_sheet` - Expense sheet reports ### Affected Versions - 18.0+ (17.0 theoretical; cloud_storage wasn't implemented, so doesn't make sense) ### Reproduction Steps #### Option A: HR Expense Report 1. Create HR expense record 2. Add attachment with type=url/cloud_storage pointing to valid PDF URL 3. Link attachment to hr.expense record 4. Generate expense report → TypeError occurs #### Option B: Vendor Bill Report 1. Create vendor bill (account.move) 2. Add attachment with type=url/cloud_storage pointing to valid PDF URL 3. Link attachment to account.move record 4. Print Original Vendor Bill → TypeError occurs ### Error Details ```python TypeError: a bytes-like object is required, not 'bool' at /odoo/tools/pdf/__init__.py:220 in to_pdf_stream from /odoo/addons/hr_expense/models/ir_actions_report.py:29 ``` #### Reference Client demo: https://drive.google.com/file/d/1HUvZqZ21NiX34T2IQhuVNbLP41xSV7jq/view OPW-5036638 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226094
This fixes an accounting issue where taxes added during bank reconciliation could be counted twice in cash basis tax reports. Tax reports now reflect the correct amount when invoices are partially matched with bank statement entries and an adjustment line is added.
Original PR description
**Steps to reproduce:** - Install Accounting - In Accounting settings, activate "Cash Basis" - Create/modify a tax with "Tax Exigibility" set to "Based on Payment" - Set an account as "Cash Basis…
**Steps to reproduce:**
- Install Accounting
- In Accounting settings, activate "Cash Basis"
- Create/modify a tax with "Tax Exigibility" set to "Based on Payment"
- Set an account as "Cash Basis Transition Account"
- Create an invoice:
* Customer: [any]
* Invoice Lines:
- [Price] 200.0
- [Taxes] The cash basis tax (e.g. 15%)
- Confirm the invoice
- Go to "Bank" journal
- Create a bank statement for a lower amount than the invoice (e.g. $200)
- Match the statement with the invoice from the "Match Existing Entries" tab
- Select the added line and click on "fully paid" link
=> A new line with the amount difference should be added
- On the new line, select an expense account and the cash basis tax
=> A new tax line should be added (e.g. $3.91)
- Validate
- Go to "Accounting / Reporting / Statement Reports / Tax Report"
**Issue:**
The amount of the Tax is equal to:
[Tax amount of the invoice] - 2 * [Tax amount of the difference line] = $30 - 2 * $3.91 = $22.18
which is not correct.
The tax amount of the difference line (coming from the bank reconciliation widget) is taken twice into account.
**Cause:**
A cash basis move is created for the tax line created in the bank reconciliation widget.
This move is using the same tax account as debit and credit account and is directly reversed using the same account.
No cash basis move should be created for that line because the tax line is added while reconciling a bank statement, which means the tax should have been received.
**Solution:**
Do not create a cash basis move for journal entries made in a bank journal.
opw-4663059
Forward-Port-Of: odoo/enterprise#94899
Forward-Port-Of: odoo/enterprise#93735Subscription invoices that include combo products can now be created and confirmed without triggering accounting errors. This prevents failed invoice validation and automated payment processing interruptions for affected subscription orders.
Original PR description
Currently, an error is produced while creating an invoice for a subscription order with combo products, and it can be triggered in two different ways. 1. Directly create an invoice. - Create and…
Currently, an error is produced while creating an invoice for a subscription order
with combo products, and it can be triggered in two different ways.
1. Directly create an invoice.
- Create and confirm a subscription with a combo product.
- Create an invoice for this subscription and try to confirm it.
- Validation error shown in display and error generated in log
2. When cron "Payment: Post-process transactions" trigger:
- Enable the Automatic Invoice option in the Subscription settings.
- Activate a demo payment provider (e.g. Demo: Payment Provider).
- Create and confirm a subscription that includes a combo product.
- Click on "Pay" to process the subscription payment.
- An error occurs when the above-mentioned cron is triggered, and it
tries to create an invoice for a subscription order.
Error: `new row for relation "account_move_line" violates check constraint
"account_move_line_check_accountable_....`
This issue arises during the creation of an account move line for deferred entries for
the 'Combo Product' column of the original invoice (subscription):
- At [1], `deferred_start_date` and `deferred_end_date` were added to all invoice line values within `_prepare_invoice_line` used to create the original invoice
- Then, at [2], during confirmation of the `original invoice`, the code attempts to generate `deferred entries` for for move where any move lines that has a `deferred_start_date`
- At code line [3], during the generation of deferred entries, an account move line is created without an associated `account_id`
- During `display_type` computation at [Code](https://github.com/odoo/odoo/blob/9ec4e0d3c5f1aaff0b36dc5def1e69b8285c3be1/addons/account/models/account_move_line.py#L480-L484), `line.move_id.is_invoice()` evaluates to `False`. As a result, the line is assigned a `display_type` as a 'product'.
- Since `display_type` is 'product' and `account_id` is missing, it violates the following check constraint at [Code](https://github.com/odoo/odoo/blob/9ec4e0d3c5f1aaff0b36dc5def1e69b8285c3be1/addons/account/models/account_move_line.py#L451): `CHECK(display_type IN ('line_section', 'line_note') OR account_id IS NOT NULL)`
This commit fixes the issue by preventing the addition of the `deferred_start_date` and `deferred_end_date` keys for invoice lines whose corresponding sale order lines have products of type 'combo' at [1].
[1]:- https://github.com/odoo/enterprise/blob/9642f7d8026149a6524e036c523b65ccbdf17258/sale_subscription/models/sale_order_line.py#L448-L449
[2]:- https://github.com/odoo/enterprise/blob/9642f7d8026149a6524e036c523b65ccbdf17258/account_accountant/models/account_move.py#L113-L114
[3]:- https://github.com/odoo/enterprise/blob/9642f7d8026149a6524e036c523b65ccbdf17258/account_accountant/models/account_move.py#L309
sentry-6763423503
Forward-Port-Of: odoo/enterprise#90989Follow-up PDF reports now correctly handle attachments stored as remote URLs or in cloud storage. This prevents report generation failures and ensures customers can produce follow-up documents regardless of where attachments are stored.
Original PR description
### Issue PDF reports fail when attachments are remote URLs or cloud storage resources. The to_pdf_stream() method expects local file data but receives boolean values from remote attachments, causing a TypeError. ### Solution Download remote resources before processing them in PDF reports. This ensures all attachments have accessible data regardless of storage type. ### Affected Reports (enterprise): - account_followup.report_followup_print_all [Community PR](https://github.com/odoo/odoo/pull/226094) OPW-5036638 Forward-Port-Of: odoo/enterprise#94477