Saturday, April 18, 2026
6 changes · saas-18.3
Resolved issues and error corrections
This update resolves an issue where users without stock access couldn't duplicate Helpdesk tickets with associated sales. The fix sets the product ID to 'false' during duplication for non-stock users, allowing them to create copies of tickets and their linked sales information. This improves usability for all users.
Original PR description
Steps to reproduce: - Install helpdesk_sale_timesheet. - Create a Helpdesk Ticket and set its sale_line_id. - Log in as a user without stock.group_stock_user access. - Try to duplicate the ticket. Issue: Duplicating a ticket raises an AccessError because the user lacks stock rights required when copying the product_id. Fix: Set `product_id` to False during duplication for non-stock users. Reference: https://github.com/odoo/enterprise/pull/9100 task-5356318 Forward-Port-Of: odoo/enterprise#113323 Forward-Port-Of: odoo/enterprise#101338
This update prevents the system from creating refund payments when an uncaptured Stripe payment is voided. Previously, a refund was automatically generated, even though no payment had been collected. This change ensures accurate accounting and avoids unnecessary refund processing.
Original PR description
When an uncaptured Stripe payment is voided, the system will still generate the refund payment entry. Steps to reproduce: - Configure the Stripe payment provider - enable "Capture Manually" - generate webhook - Create a sales order - Generate a payment link and pay with Card - Back to the SO, click 'Void Transaction' Issue: Refund payment entry will be created even if no payment has been collected for the transaction. opw-5866924 Forward-Port-Of: odoo/odoo#259230
This update resolves an issue where invoices could fail to update their Peppol status, leading to inaccurate reporting. The fix involved correcting a configuration error that was preventing the system from properly processing Peppol invoice requests. This ensures accurate tracking of invoice status within the Peppol network.
Original PR description
1. Send an invoice that will return an error when send to IAP 2. Send the invoice 3. Click "Fetch Peppol Invoice status" on the dashboard 4. There is a traceback (see the bottom of this message) To…
1. Send an invoice that will return an error when send to IAP
2. Send the invoice
3. Click "Fetch Peppol Invoice status" on the dashboard
4. There is a traceback (see the bottom of this message)
To create an invoice that will return an error I locally removed the EndpointID from the UBL generation (and the constraint to check that during the genreation).
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 42, in call_button
action = call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/account_journal.py", line 34, in peppol_get_message_status
edi_users._peppol_get_message_status()
File "/home/odoo/src/odoo/addons/account_peppol/models/account_edi_proxy_user.py", line 287, in _peppol_get_message_status
processed_message_uuids = edi_user._peppol_process_messages_status(messages_to_process, uuid_to_record)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol_response/models/account_edi_proxy_user.py", line 180, in _peppol_process_messages_status
peppol_response = uuid_to_record[uuid]
^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'document_type'
```
task-None
Forward-Port-Of: odoo/odoo#259834This update fixes a potential issue that could cause incorrect behavior after uninstalling modules in Odoo. Previously, outdated references within the system's data structure lingered, leading to problems with how the system tracked relationships. Now, the system clears all relevant caches during uninstall, ensuring a cleaner and more reliable experience.
Original PR description
When uninstalling a module, the ORM may replace field objects in the registry via a prefetch patch to avoid fetching deleted fields. The previous code only called lazy_property.reset_all(), which resets lazy-property caches, but left _field_trigger_trees and _is_modifying_relations intact. Those structures still held references to the old field objects, and could be consulted by subsequent ORM operations, leading to incorrect trigger resolution or relation tracking. Clear both caches whenever a shared field has been patched so all registry state stays consistent with the new field objects. runbot-242251 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#259820
This update fixes an issue where returning inter-company deliveries incorrectly credited the stock input account instead of reversing the original debit. By including transit locations as valid locations, the system now correctly handles returns, mirroring standard return behavior and ensuring accurate accounting for inter-company transactions. This ensures consistent and reliable financial reporting.
Original PR description
### Problem: When returning a delivery or receipt for an inter-company transaction, the journal entry created for the return will account on the opposite stock interim account. That is, a delivery to…
### Problem:
When returning a delivery or receipt for an inter-company transaction, the journal entry created for the return will account on the opposite stock interim account. That is, a delivery to another company will debit the stock output account, but returning the delivery will create an account move that credits the stock input account. Compare this to normal return behavior which will credit the stock output account to reverse the original delivery's entry.
### Solution:
When deciding whether a stock move is a return, we will include transit locations as valid locations.
### Steps to reproduce (Runbot v18)
- Automatic accounting
1. Create a SO for the automatically accounted product, selling to another company in the system
2. Validate the delivery, check the valuation and note there is a debit on the stock output account
3. Create a return for the delivery and validate it, check the valuation and note the credit on the stock input account
To clarify, this differs from when the customer on the SO is anything other than a res.company, where we will see a credit on the stock output account when the return is validated.
Also, this flow is the same for POs, and the same bug is addressed by this fix.
### Before
<table>
<th>Move type</th>
<th>Account</th>
<th>Debit</th>
<th>Credit</th>
<tr>
<td>Delivery</td>
<td>Stock output</td>
<td>100</td>
<td>0</td>
</tr>
<tr>
<td>Delivery Return</td>
<td style="{color: red}">Stock input</td>
<td>0</td>
<td>100</td>
</tr>
</table>
### After
(Or normal behavior without inter-company transfer)
<table>
<th>Move type</th>
<th>Account</th>
<th>Debit</th>
<th>Credit</th>
<tr>
<td>Delivery</td>
<td>Stock output</td>
<td>100</td>
<td>0</td>
</tr>
<tr>
<td>Delivery Return</td>
<td>Stock output</td>
<td>0</td>
<td>100</td>
</tr>
</table>
opw-5993147
Forward-Port-Of: odoo/odoo#255439This update resolves an issue where users attempting to save a customer record with an invalid Taiwan VAT number (e.g., containing letters) would experience a crash. The fix adds validation to ensure the VAT number consists only of digits, preventing the error and providing a clear warning message to the user.
Original PR description
**Steps to reproduce:** - Install the `base_vat` module. - Navigate to Invoicing > Customers. - Create a new contact and set the country to `Taiwan`. - Enter `1234567A` as the `Tax ID` and try to `save`. **Error:** `ValueError: invalid literal for int() with base 10: 'A'` **Root cause:** At [1], `check_vat_tw` is missing validation to ensure that the VAT number (without the country code) contains only digits, which causes an error when calling the `int()` method on the VAT number. **Fix:** This commit prevents errors and ensures users receive a `clear warning message`. [1]: https://github.com/odoo/odoo/blob/23398d24e108875b2838715d4b366df265d53234/addons/base_vat/models/res_partner.py#L929-L958 **No task Id** Forward-Port-Of: odoo/odoo#259936 Forward-Port-Of: odoo/odoo#259847