Sunday, August 30, 2026
10 changes · saas-19.2
Resolved issues and error corrections
This fix prevents duplicate calendar entries when an Outlook event that was already synced is later changed into a recurring meeting in Outlook. The calendar now removes the old single entry once the recurring series is created, keeping users' schedules accurate and uncluttered.
Original PR description
When a single event already synced with Outlook is turned into a recurring event directly in Outlook, Microsoft reuses the event in place: the seriesMaster keeps the iCalUId of the former single event, while each occurrence gets a fresh id/iCalUId. On resync, a seriesMaster is only matched against calendar.recurrence, never against calendar.event. As no recurrence exists yet, it is handled as a brand new recurrence whose occurrences are created from scratch. The original single event, which shares the master's iCalUId and the first occurrence's timeslot, is then left untouched. Drop that pre-existing single event when building a new recurrence from an inbound seriesMaster, since it is now represented by the recurrence itself. opw-5129848 Forward-Port-Of: odoo/odoo#285196 Forward-Port-Of: odoo/odoo#271787
This fix ensures Odoo can efficiently reload related records after cached relationship data has been cleared. It helps avoid unnecessary database lookups and supports smoother performance in areas that depend on relational data, with an additional point of sale permission fix for reconciliation during tests.
Original PR description
For relational fields, the prefetch is built from the cache. It evolves dynamically with changes. Therefore, cache invalidation will remove prefetch even on existing recordsets. In such a case, if the cache of the field was cleared, we will try to rebuild the cache. This way, accessing a recordset that uses a relational prefetch will try to rebuild it. In the test, without this, we would get 40 queries because there are 2 fields to resolve for 20 records. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update makes document-related partner updates more reliable when access rules or cached relationship data change during a save. It also strengthens a point-of-sale localization test so failures are caught more clearly instead of producing misleading results.
Original PR description
https://github.com/odoo/odoo/pull/280270
This fix ensures Odoo uses the latest saved metadata when looking up internal record identifiers. It prevents outdated settings from being returned after a change, improving consistency for system configuration and module data handling.
Original PR description
Steps to Reproduce: - write on ir.model.data to modify noupdate. - _lookup_xmlids still returns the old noupdate value. Example: In [1]: imd = self.env['ir.model.data'] In [2]: xml_id =…
Steps to Reproduce:
- write on ir.model.data to modify noupdate.
- _lookup_xmlids still returns the old noupdate value.
Example:
In [1]: imd = self.env['ir.model.data']
In [2]: xml_id = self.env['ir.model.data'].search([], limit=1)
In [3]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[3]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, False, 149)]
In [4]: xml_id.write({'noupdate': not xml_id.noupdate})
Out[4]: True
In [5]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[5]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, False, 149)]
In [6]: imd.flush_model()
In [7]: imd._lookup_xmlids([xml_id.complete_name], self.env[xml_id.model])
Out[7]: [(18603, 'auth_signup', 'action_send_password_reset_instructions', 'ir.actions.server', 149, True, 149)]
Issue:
- _lookup_xmlids is returning values from ir.model.data executing an SQL query w/o flushing.
Fix:
- Add flushing in _lookup_xmlids.
Forward-Port-Of: odoo/odoo#262791This fixes an issue where new shoppers entering both a personal contact name and company VAT details during checkout could have their contact name overwritten by the company name. Customer records now keep the right person and company details, improving data accuracy for sales and customer follow-up.
Original PR description
Steps to produce: --- - Install website_sale module without demo. - Create a new product and publish it. - From the incognito, go to shop and add that product to cart. - While doing checkout > fill…
Steps to produce: --- - Install website_sale module without demo. - Create a new product and publish it. - From the incognito, go to shop and add that product to cart. - While doing checkout > fill the address form. - Add the all details including the company name and valid VAT. (ex. BE0477472701) - Submit the form. Issue: --- - When a public or guest user submits a new address with both a contact name and a company name along with a valid VAT number, the contact's name was being overwritten with the company name. Root cause: --- - The _compute_is_company heuristic in res.partner automatically sets is_company=True for partners with valid VAT. In [commit] `_create_or_update_address`, the condition `elif partner_sudo.is_company:` was designed to rename existing companies, but incorrectly caught newly created individuals marked as companies due to VAT, causing their name to be overwritten instead of creating a parent company. Solution: --- - Replaced the is_company check with explicit conditions: the partner has no parent_id, has contact-type child_ids. - This ensures the rename-company branch only fires for actual company heads that the logged-in user belongs to, not for individuals that happen to have is_company=True due to a valid VAT. [commit]: https://github.com/odoo/odoo/commit/8f3a32170c842f5f42edc79bf8620276f0da7be4 opw-6356772 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275044
This update brings the spreadsheet component to its latest version for this Odoo release. It improves keyboard focus visibility for radio selections and fixes radar chart point coloring, making spreadsheets clearer and easier to use.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/9e63c606e7 [REL] 19.2.27 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/9e63c606e7 [REL] 19.2.27 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/82cd782d55 [FIX] radio_selection: add focus style [Task: 6384097](https://www.odoo.com/odoo/2328/tasks/6384097) https://github.com/odoo/o-spreadsheet/commit/6600636c84 [FIX] chart: set point color for radar charts [Task: 6474893](https://www.odoo.com/odoo/2328/tasks/6474893) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
This fix prevents an upgrade failure for Indian localization users when a cash rounding setting is tied to an open Point of Sale session. The existing cash rounding configuration is now preserved during upgrades, avoiding an error that could interrupt the move from version 19.2 to 19.3.
Original PR description
An issue occurs during the database upgrade From version 19.2 to 19.3. During the upgrade, the system attempts to update the `name` and `rounding` configuration of the Cash Rounding account. If the…
An issue occurs during the database upgrade
From version 19.2 to 19.3.
During the upgrade, the system attempts to update
the `name` and `rounding` configuration of the Cash Rounding account.
If the Cash Rounding record is linked to
an open POS session, the update fails with
the following constraint error:
```
You are not allowed to change the rounding configuration while a POS session using it is already opened.
```
To avoid this traceback during the upgrade,
set the record's noupdate attribute to True so that it is not modified.
```
File "/home/odoo/src/odoo/saas-19.3/odoo/tools/convert.py", line 485, in _tag_record
record = model._load_records([data], self.mode == 'update')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py", line 4566, in _load_records
data['record']._load_records_write(data['values'])
File "/tmp/tmpxr_9kp1h/migrations/base/0.0.0/pre-models-load_write.py", line 46, in _load_records_write
return super()._load_records_write(values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py", line 4487, in _load_records_write
self.write(values)
File "/home/odoo/src/enterprise/saas-19.3/ai_fields/models/models.py", line 57, in write
res = super().write(vals)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/ai/models/models.py", line 339, in write
return super().write(vals)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py", line 3860, in write
real_recs._validate_fields(vals, inverse_fields)
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py", line 1295, in _validate_fields
check(records)
File "/home/odoo/src/odoo/saas-19.3/addons/point_of_sale/models/pos_order.py", line 1575, in _check_session_state
raise ValidationError(
odoo.exceptions.ValidationError: You are not allowed to change the rounding configuration while a pos session using it is already opened.
```
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#281174This fixes Spanish labels used for Latin American identification types in Odoo 19. Business users will now see VAT shown as "NIF" and Passport shown as "Pasaporte", avoiding confusion in contact and localization workflows.
Original PR description
In Odoo 19, translations for l10n.latam.identification.type were moved from .po files to inline columns in the CSV data file. The es_419 correction previously applied via es_419.po (VAT → NIF) was…
In Odoo 19, translations for l10n.latam.identification.type were moved from .po files to inline columns in the CSV data file. The es_419 correction previously applied via es_419.po (VAT → NIF) was never ported to the new CSV mechanism, causing "IVA" to reappear. Passport was also missing its es_419 translation.
**Description of the issue/feature this PR addresses:**
In Odoo 17 and 18, the Spanish (es_419) translation of the VAT identification type was corrected from "IVA" to "NIF" (Número de Identificación Fiscal) via the es_419.po file in l10n_latam_base. In Odoo 19, the translation mechanism for this data changed: translations are now stored as name@es_419 columns directly in l10n_latam.identification.type.csv. The correction was never applied to this new file, so the wrong value ("IVA") reappeared. Additionally, the Passport type was missing its es_419 translation entirely.
**Current behavior before PR:**
- In any Odoo 19 instance with a Latin American localization, the identification type dropdown shows "IVA" for the VAT type (es_419 locale).
- The Passport type shows the untranslated English label "Passport" in es_419 locales.
**Desired behavior after PR is merged:**
- The VAT identification type displays "NIF" in es_419 locales.
- The Passport identification type displays "Pasaporte" in es_419 locales.
- Behavior in v17 and v18 is unaffected (different translation mechanism).
**Steps to test the functionality:**
1. On an Odoo 19 instance with l10n_latam_base installed and language es_419 active, go to Contacts → Configuration → Identification Types.
2. Verify that the type with external ID l10n_latam_base.it_vat shows "NIF" (not "IVA").
3. Verify that the type with external ID l10n_latam_base.it_pass shows "Pasaporte" (not "Passport").
4. Open a contact form, set country to Argentina, and confirm the identification type dropdown reflects the corrected labels.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272243This fixes a Point of Sale loyalty issue where “Buy 2 Take 1” rewards based on product tags were not automatically applied when cashiers changed quantity with the numpad or scanned weighted quantities. Eligible free products are now granted consistently, reducing missed promotions and checkout corrections.
Original PR description
Steps to reproduce: - create a "Buy 2 Take 1" program whose rule and reward both target a product tag containing several products - in the PoS, add one of the tagged products to the order - set its…
Steps to reproduce: - create a "Buy 2 Take 1" program whose rule and reward both target a product tag containing several products - in the PoS, add one of the tagged products to the order - set its quantity to 3 with the numpad Issue: The free product is not given. Clicking the product a third time instead of typing the quantity does give it, and so does a program whose reward is a single product. Cause: A reward whose products come from a tag is multi_product, so getClaimableRewards never computes its unclaimed quantity and the auto claim of updateRewards skips it: which product to give out is unknown. The only place claiming such a reward is addLineToCurrentOrder, which resolves it with the product that was just added. Setting a quantity does not go through it, hence the difference. Fix: Resolve the reward product the same way when auto claiming: the product of the line being worked on, or, failing that, the only reward product the order contains. The reward then follows the quantity of any of the tagged products, not only of the first one added, and the cashier is still asked when the order does not settle the choice. opw-6430385 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284777
This fixes an Outlook calendar sync issue where changing one moved occurrence in a recurring event could cause all occurrences to be deleted and recreated with that occurrence's details. Recurring event updates now distinguish real schedule pattern changes from harmless start-date metadata changes, helping keep attendees and event edits limited to the intended occurrence.
Original PR description
The stored rrule of a recurrence embeds a DTSTART line based on the recurrence dtstart (the smallest start among its events). When the first occurrence is moved in Outlook, the Odoo dtstart no longer…
The stored rrule of a recurrence embeds a DTSTART line based on the recurrence dtstart (the smallest start among its events). When the first occurrence is moved in Outlook, the Odoo dtstart no longer matches that DTSTART, but the stored rrule is not recomputed at that point (it only depends on the pattern fields). On a later sync touching the seriesMaster (e.g. after adding an attendee to the moved occurrence), the recurrence values are written again and the rrule is reserialized with a DTSTART based on the moved occurrence. _write_from_microsoft() took this new rrule string as a pattern change and reapplied the recurrence: all occurrences were deleted and recreated as copies of the moved one, spreading its specific data (e.g. the newly added attendee) to the whole series. Ignore the DTSTART line when comparing the rrule before and after the write: a DTSTART-only difference does not reflect any pattern change in Outlook. An actual pattern change (FREQ, UNTIL, INTERVAL, ...) still reapplies the recurrence as before. Steps to reproduce: 1. In Outlook, create a recurring event 2. In Odoo, run the calendar sync 3. In Outlook, move the first occurrence of the recurrence (shift its start and stop time by 30 minutes) 4. In Odoo, run the sync 5. In Outlook, add an attendee to that same first occurrence 6. In Odoo, run the sync All the occurrences are deleted and recreated as copies of the first one, and the attendee ends up on every occurrence instead of one. opw-5129848 Forward-Port-Of: odoo/odoo#284747 Forward-Port-Of: odoo/odoo#269549