Daily updates from Odoo
Thursday, July 30, 2026
15 changes · 17.0
New functionality added to Odoo
* = l10n_fr_pdp_pos last backported commit: 373711ba04bd2585f51be26cec31cd80d21d0571 The main difference for the e-invoicing part are the difference in - peppol (i.e. partner and company / settings) - the account move send wizard They were both refactored between 17.0 and 18.0 task-6356968 For the e-reporting part Co-authored-by: Jérémy Bazin (baje) <baje@odoo.com> #### [IMP] l10n_fr_pdp: backport Flow 10 e-reporting Flow 10 e-reporting is needed on 17.0 while its imple
Original PR description
* = l10n_fr_pdp_pos last backported commit: 373711ba04bd2585f51be26cec31cd80d21d0571 The main difference for the e-invoicing part are the difference in - peppol (i.e. partner and company / settings)…
* = l10n_fr_pdp_pos last backported commit: 373711ba04bd2585f51be26cec31cd80d21d0571 The main difference for the e-invoicing part are the difference in - peppol (i.e. partner and company / settings) - the account move send wizard They were both refactored between 17.0 and 18.0 task-6356968 For the e-reporting part Co-authored-by: Jérémy Bazin (baje) <baje@odoo.com> #### [IMP] l10n_fr_pdp: backport Flow 10 e-reporting Flow 10 e-reporting is needed on 17.0 while its implementation was introduced in 18.0. The business builder can be reused, but account EDI helper signatures and company account fields differ between versions. Keep the 18.0 dict_to_xml rendering so node ordering, omissions and control-character sanitization remain identical. Add the local tax compatibility required for configured exemptions, acquisitions, reverse charge and UoM codes. Also adapt account lookup to the 17.0 company field. Validate the generated report against the 0290 reserve fixture and cover invalid XML control characters. Compose the e-reporting chatter markup without concatenating translated strings. This preserves the reference payload while keeping e-reporting separate from the ongoing e-invoicing backport. task-6356968 #### [ADD] l10n_fr_pdp_pos: backport Flow 10 POS e-reporting POS e-reporting depends on closing entries being included in Flow 10. The 18.0 implementation relies on POS and accounting fields and APIs which are not available on 17.0. Detect closing entries through pos.session.move_id, adapt order creation tests to create_from_ui, and extend the Flow 10 query. Filter 17.0 POS counterpart lines because they are still marked as product lines. Preserve the sign of separate refund income lines so sales and refunds are reported net. This preserves the 18.0 reporting result without changing the e-invoicing path. task-6356968
Enhancements to existing features
Supersedes #275986 and fixes its approach: that PR updates the withholding rates **in place** on the existing tax records (`ret_10_income_person`, `ret_10_income_rent`, `ret_2_income_person`, and repurposes `ret_2_income_transfer` into a different concept). Those records exist in production databases with posted history behind them, and the pre-law rates remain legally applicable to operations dated before the law's entry into force, so rewriting them breaks prior-period postings, corrections an
Original PR description
Supersedes #275986 and fixes its approach: that PR updates the withholding rates **in place** on the existing tax records (`ret_10_income_person`, `ret_10_income_rent`, `ret_2_income_person`, and…
Supersedes #275986 and fixes its approach: that PR updates the withholding rates **in place** on the existing tax records (`ret_10_income_person`, `ret_10_income_rent`, `ret_2_income_person`, and repurposes `ret_2_income_transfer` into a different concept). Those records exist in production databases with posted history behind them, and the pre-law rates remain legally applicable to operations dated before the law's entry into force, so rewriting them breaks prior-period postings, corrections and reports. Following the approach used for equivalent legal rate changes in other localizations on stable branches (`l10n_ee`, `l10n_sk`, `l10n_fi`), this PR adds **new taxes** for the new rates, keeps the pre-law taxes active, archives the superseded 27% remittance withholding, gives the new 15% withholding its own payable account instead of reusing the one tied to L253-12, and leaves the module authorship untouched.
## Description
Dominican Republic Law 30-26 ("medidas pro-crecimiento económico, simplificación fiscal y mitigación de la crisis internacional"), enacted on June 18, 2026, amends several provisions of the Tax Code that affect taxes shipped with the `l10n_do` chart template:
| Concept | Before | After | Effective |
|---|---|---|---|
| ISR withholding on fees/services provided by individuals (art. 309 b) | 10% | 15% (payment on account) | July 2026 |
| ISR withholding on rents paid to individuals (art. 309 a) | 10% | 15% (single and final) | July 2026 |
| ISR withholding on payments abroad for software licenses/subscriptions, royalties, online advertising and cloud data storage (arts. 305-1 / 305-2) | 27% (general remittance rate) | 15% (single and final) | June 18, 2026 |
| ISR withholding on technical services provided by individuals (art. 309 rate over the 20% presumed base of art. 70, Regulation 139-98) | 2% effective | 3% effective | July 1, 2026 (DGII notice 10-26) |
Changes:
- New taxes `ret_15_income_person` and `ret_15_income_rent`. The pre-law 10% taxes are kept active since their rates remain applicable to operations dated before the law.
- New taxes `ret_3_income_person` and `ret_3_income_transfer` for the effective 3% withholding on technical services, posting to a new payable account `l10n_do_21030311` ("Other Withholdings (L30-26)") since their pre-law counterparts' accounts are tied to previous regulations; the pre-law 2% taxes also remain active.
- New tax `ret_15_income_remittance_tech`, posting to a new payable account `l10n_do_21030310` ("ISR Withheld on Remittances Abroad (L30-26)"), since the existing remittance account is tied to L253-12.
- `ret_27_income_remittance` is deactivated in the template, superseded by the new reduced withholding.
The new tax names follow the module's existing convention of tagging the enforcing law (as with "(L253-12)").
No changes are needed in the tax report: the ISR withholding taxes only distribute to payable accounts, without tax grids.
Scope note: Law 30-26 also raises the tax on checks and electronic transfers from 1.5‰ to 2.0‰ (art. 382 of Law 288-04, as amended), deliberately left out here: it is not an invoiceable tax — banks withhold it directly on account debits, so it is handled outside invoice accounting.
References:
- https://presidencia.gob.do/leyes/ley-30-26
- https://www.hacienda.gob.do/ley-30-26-no-dispone-impuestos-por-suscripciones-de-ciudadanos-a-plataformas-digitales-reduce-de-27-a-15-la-retencion-a-empresas-que-contratan-servicios-tecnologicos-en-el-exterior/Resolved issues and error corrections
The aged payable and receivable report drill-downs now show only items that still have an outstanding balance. This prevents already paid invoices, bills, payments, or write-offs from appearing in the details, making the report easier to trust and reconcile.
Original PR description
Steps to Reproduce: 1. Create a partner (vendor or customer) with multiple bills/invoices, respectively. 2. Fully pay one or more, leaving at least one for the same partner still open. 3. Open…
Steps to Reproduce: 1. Create a partner (vendor or customer) with multiple bills/invoices, respectively. 2. Fully pay one or more, leaving at least one for the same partner still open. 3. Open Accounting > Reporting > Partner Reports > Aged Payable/Receivable. 4. Click into the total aging bucket cell for that partner. Issue: The drill-down list shows bills/invoices that are already fully settled (`amount_residual = 0.00`) alongside those that are genuinely outstanding. Affects both Aged Payable and Aged Receivable, since both share the same underlying method. Only appears when the partner has at least one open balance; if everything is paid, there's no bucket to drill into, so the bug doesn't surface. Root Cause: Bucket totals (`_aged_partner_report_custom_engine_common`) correctly recalculate each line's residual from `account_partial_reconcile` and exclude zero-residual lines via a `HAVING` clause. The drill-down list, however, is built separately by `aged_partner_balance_audit`, whose domain only filters by reconcile flag, journal type, and date range - it never checks amount_residual, so every line in that window gets listed regardless of payment status. Fix: Added (`'amount_residual', '!=', 0`) to the domain in aged_partner_balance_audit. Since this method is shared by both reports (differentiated only by `journal_type`), one fix covers both. Result: Both drill-downs now correctly exclude settled bills, invoices, payments, and write-offs, showing only genuinely outstanding items. opw : 6333699
This fix prevents the Journal Report from failing when an invoice uses a tax that was originally a group of taxes but later changed to a percentage tax. Accounting users can now open audit reports reliably even after tax configuration changes.
Original PR description
**Steps to reproduce:** - Install account_reports - Create a tax * Tax Computation: Group of Taxes * Definition: [Add a tax] - Create an invoice with that tax - Confirm the invoice - Edit the tax by changing "Tax Computation" to "Percentage" - Go to "Accounting / Reporting / Audit Reports / Journal Report" **Issue:** A KeyError is raised. **Cause:** While generating the data, a group of taxes is found in the journal items. When trying to retrieve its info from the dict listing the groups of taxes, its ID is not found but the system assumes that it's present. opw-6377465
This fix prevents worksheet report generation from failing when a chatter section is added through Studio. Chatter-related fields are now ignored when building the printable report, so users can save and print worksheet templates reliably.
Original PR description
Steps to reproduce: - Enable Studio - Create a worksheet template - Design the template in Studio - Add a Chatter on the form view - Save Issue: Adding a chatter to a worksheet template's model crashes the report generation. `_get_qweb_arch` builds the set of fields to display in the printed report directly from the form view's fields, without excluding the ones living inside the `oe_chatter` div (message_ids, message_follower_ids, activity_ids). Those fields then end up with a t-field in the generated qweb template, which crashes when rendered since they aren't meant to be displayed outside of the chatter widget. To fix this we xclude fields that are descendants of the `oe_chatter` div when collecting the form view's fields, the same way `mail`'s `_postprocess_tag_field` already skips them for regular form view postprocessing. This is already fixed in 18.0 thanks to https://github.com/odoo/odoo/pull/156463 and https://github.com/odoo/enterprise/pull/58055 opw-6397700
Accounting users in Spanish companies can now export VAT record books that include Point of Sale transactions without needing Point of Sale access. The report safely reads the required POS data internally, preventing access errors and keeping tax reporting workflows uninterrupted.
Original PR description
Steps to reproduce:
- With an ES Company
- Open a POS session, add product with tax and pay
- As a user with only accounting access
- Go to Accouting > Reporting > Tax report
- Select Generic Tax report
- Print "VAT record Books"
Issue:
An AccessError will raise
```
Access Error
You are not allowed to access 'Point of Sale Session' (pos.session) records.
This operation is allowed for the following groups:
- Point of Sale/User
Contact your administrator to request access if necessary.
```
Analysis:
Vat Record Books handler for POS needs to read pos.session and pos.order records. Currently, the action is performed with the rights of the user running the report, so accounting-only user face an error.
As POS records are only read internally to build the report, we add sudo call to get the data.
opw-5862529This fixes an issue where work orders in the Shop Floor view could appear in an inconsistent order after refreshing or changing filters. The view now preserves the intended order based on work order status and scheduled start date, helping production teams see tasks reliably.
Original PR description
Records already in cache are intended to be sorted by their position in `recordCacheIds` to preserve the previously computed display order. However, `recordCacheIds` stores database record ids (`resId`), and currently the cache lookup incorrectly uses `id` instead. As a result, every lookup returns `-1`, and could lead to inconsistent ordering. Steps to reproduce: 1. Create several manufacturing orders with work orders assigned to the same work center. 2. Give the work orders different states and scheduled start dates. 3. Open Shop Floor and display that work center. 4. Refresh the view or change a filter so the records are recomputed. It should use `resId` so the previously computed display order remains, which is based on state and scheduled start date. Related: odoo/enterprise#74421 opw-6402233
Quotations created from repair orders linked to helpdesk tickets now correctly use the salesperson assigned to the customer. This prevents missing sales ownership on these quotations and helps teams track responsibility and follow-up accurately.
Original PR description
Currently, when a quotation is created from a repair order generated from a helpdesk ticket, the salesperson is not set on the quotation even if the customer has a salesperson assigned. **Steps to…
Currently, when a quotation is created from a repair order generated from a helpdesk ticket, the salesperson is not set on the quotation even if the customer has a salesperson assigned. **Steps to Reproduce:** - Install `helpdesk_repair`. - Go to `Helpdesk` > `Configuration` > `Helpdesk Teams`. - Open a team recod and enable `Repairs`. - Create a `contact/customer` with a `salesperson` assigned. - Go to `Helpdesk`, create a ticket for that `customer`, and select the `helpdesk team` configured above. - Click `Repair`, then click `Create Quotation`. - Open the quotation and check the `Salesperson` field in the `Other Info` tab. **Current behavior:** The Salesperson field on the quotation remains empty. **Expected behavior:** The Salesperson field on the quotation should inherit the salesperson assigned to the selected customer/contact. **Cause of the issue:** When a repair order is created from a helpdesk ticket, default_user_id [1] is passed in the context . This value is propagated when creating the repair order [2] . Later, when creating the quotation from the repair order [3], the same context is reused. Because default_user_id is already present in the context, it overrides the precomputation of user_id from the customer. As a result, user_id is initialized with an empty value and remains unset. **Fix:** This commit ensures that default_user_id is removed from the context before creating the sale order. Without a default value for user_id, the field is correctly precomputed from the selected customer, and the salesperson is properly assigned. [1]- https://github.com/odoo/enterprise/blob/2662932c7ac8ebf3ed5a05d44d7ebfaff869fcbd/helpdesk_repair/models/helpdesk_ticket.py#L52 [2]- https://github.com/odoo/enterprise/blob/2662932c7ac8ebf3ed5a05d44d7ebfaff869fcbd/helpdesk_repair/models/helpdesk_ticket.py#L36-L40 [3]: https://github.com/odoo/odoo/blob/29328b8fccff833c14de317b51f3b4e5a8c40f75/addons/repair/models/repair.py#L357 opw-6344939
Quality team email aliases now keep the correct company assigned, even when the company field is hidden or left blank. This ensures incoming emails can create quality tickets consistently in single-company and multi-company setups.
Original PR description
Issue Before This Commit: ---------------------------------- In a single-company environment, the quality team email alias was created without a company ID. As a result, incoming emails could not…
Issue Before This Commit: ---------------------------------- In a single-company environment, the quality team email alias was created without a company ID. As a result, incoming emails could not generate quality tickets, making the email alias ineffective. Steps to produce: ---------------------------------- - Install `quality_control` in a single-company environment. - Create a quality team with a name and an email alias. - Navigate to Settings → Technical → Aliases and check the newly created alias. - The Company ID is False, preventing the creation of new tickets via email. Cause ---------------------------------- In a single-company environment, the company_id field is not visible, is not required, and has no default value, so it is never set. The same issue can also occur in a multi-company environment when the user explicitly creates a team without selecting a company. After this Commit: ---------------------------------- The company_id is now set in the alias default values based on the quality team’s company. It is also updated whenever the team’s company changes, ensuring consistency and allowing incoming emails to reliably create quality tickets in all environments. Task ID: 4595798
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatte
Original PR description
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also…
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatter(ignore_record_keys=[])` The purpose was to be able to easily include all keys and ignore the default ingnore list, but this makes the additional blacklisting of a few keys more tedious, and the general usage and implementation more complex `JSONFormatter(ignore_record_keys=[*JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS, 'other key'])` To simplify the logic, **this is not the case anymore**, so to include all keys something like this would be needed `JSONFormatter(additional_record_keys=JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS)` Or an hardcoded list.
- `s_three_columns` cards could end up with mismatched heights: `equalizeCardHeights` now measures header height directly instead of deriving it from the already-stretched card container. - Links appeared with a black background: exclude `btn-link` from background-color application. - Background images didn't stretch: pass `preserve_comments` so the DPI-scaling fix comment isn't stripped from the sent email. opw-6044725 --- I confirm I have signed the CLA and read the PR guidelines at w
Original PR description
- `s_three_columns` cards could end up with mismatched heights: `equalizeCardHeights` now measures header height directly instead of deriving it from the already-stretched card container. - Links appeared with a black background: exclude `btn-link` from background-color application. - Background images didn't stretch: pass `preserve_comments` so the DPI-scaling fix comment isn't stripped from the sent email. opw-6044725 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278862
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/974b7fa15b [REL] 17.0.105 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/45bd72d8f4 [FIX] ui_sheet: `getCellWidth` getter for non-active sheet [Task: 6409426](https://www.odoo.com/odoo/2328/tasks/6409426) 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>
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/974b7fa15b [REL] 17.0.105 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/45bd72d8f4 [FIX] ui_sheet: `getCellWidth` getter for non-active sheet [Task: 6409426](https://www.odoo.com/odoo/2328/tasks/6409426) 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 commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 tas
Original PR description
This commit fixes the verification JSON. For OSS taxes no_sujeto_loc and no_sujeto, CuotaTotal and ImporteTotal must Only include the base amount, not the tax amount. See the chatter in the task for AEAT guidelines. Also removed the validation error blocking no_sujeto_loc taxes with a non-zero amount, since OSS taxes legitimately have one in Odoo accounting (e.g. 22% IT VAT) even though it is excluded from the Veri*Factu json. upgrade :- https://github.com/odoo/upgrade/pull/10799 task-5411766
Miscellaneous changes
Backport of #275640 Despite resolving the conflicts (file moved) this version also checks the python version since PyUnstable_Type_AssignVersionTag does not exists in python 3.10 To be safer, the whole logic is skipped if python < 3.13
Original PR description
Backport of #275640 Despite resolving the conflicts (file moved) this version also checks the python version since PyUnstable_Type_AssignVersionTag does not exists in python 3.10 To be safer, the whole logic is skipped if python < 3.13
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266397
Original PR description
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266397