Tuesday, September 8, 2026
13 changes · 18.0
Enhancements to existing features
Spanish SII invoice submissions now keep the XML message sent to AEAT instead of a less useful JSON record. This makes it easier for businesses to provide the required information when AEAT reports an error, improving troubleshooting and compliance support.
Original PR description
The SII submission oreviously saved the raw invoice dtaa as a JSON attachment. This is not useful cause the AEAT asks to show the XML if there is an error. The SOAP envelope sent to the AEAT is now captured using zeep's HistoryPlugin, serialised to XML and stored as an attachment instead of the JSON that was before. The tests have been updated so they compare the structure as XML instead of the JSON structure. task-6234840
Odoo now supports Sweden’s national Peppol invoice validation rules and includes missing order and requisition references in electronic invoices. This helps Swedish suppliers reduce invoice rejections and meet local e-invoicing requirements more reliably.
Original PR description
**Description of the issue/feature this PR addresses:** Sweden has adopted national PEPPOL validation rules for BIS Billing 3.0, as defined by SFTI and enforced by Peppol Authorities. These rules…
**Description of the issue/feature this PR addresses:** Sweden has adopted national PEPPOL validation rules for BIS Billing 3.0, as defined by SFTI and enforced by Peppol Authorities. These rules (SE-R-001 to SE-R-013) are not currently enforced in Odoo’s account_edi_ubl_bis3 implementation, which may lead to rejected invoices from Swedish suppliers. **Additionally, two required BIS3 fields were missing from the UBL export:** RequisitionDocumentReference from invoice.ref OrderReference from invoice.invoice_origin **Current behavior before PR:** Missing export of requisition and order references. No enforcement of Swedish national validation rules. Suppliers using SellerTaxRegistrationID are not marked with "Godkänd för F-skatt" as required. **Desired behavior after PR is merged:** Adds missing export fields to the UBL: RequisitionDocumentReference from invoice.ref OrderReference from invoice.invoice_origin Applies national Swedish validation rules (SE-R-001 to SE-R-013) during PEPPOL export. Adds "Godkänd för F-skatt" to the supplier tax registration if the supplier is Swedish. **Technical summary:** _get_partner_party_tax_scheme_vals_list extended to add "Godkänd för F-skatt" for Swedish suppliers. _export_invoice_vals extended to include requisition and order references. _invoice_constraints_peppol_en16931_ubl extended with Swedish constraints: VAT number structure and numeric checks (SE-R-001, SE-R-002) Org number format and length (SE-R-003, SE-R-004) Tax scheme requirement (SE-R-005) Allowed VAT rates (SE-R-006) Bankgiro and Plusgiro formatting (SE-R-007 to SE-R-010) PaymentMeansCode logic (SE-R-011, SE-R-012) Luhn validation of Swedish org number (SE-R-013) **Sources:** https://sfti.se/download/18.427140af179361c4e462cc34/1620641679827/Beskrivning%20av%20svenska%20valideringsregler%202018-11-12.pdf https://docs.peppol.eu/poacc/billing/3.0/bis/#national_rules
Resolved issues and error corrections
This fixes an intermittent issue where employees could see a successful sign-in message but not actually be connected in Shop Floor. The login and PIN checks now happen in order, so employees consistently appear as connected and can continue work without reloading or retrying.
Original PR description
Description of the issue/feature this PR addresses: When connecting an employee in the Shop Floor, the login request and the pin validation request are sent at the same time, because the login is not…
Description of the issue/feature this PR addresses: When connecting an employee in the Shop Floor, the login request and the pin validation request are sent at the same time, because the login is not awaited. Both of them read and write the same session, so one can overwrite the other. When that happens the login succeeds and the "Logged in!" notification is shown, but the employee is not actually connected. It only happens from time to time, when both requests overlap, which is more likely on large databases. Current behavior before PR: - The login and the pin validation are sent at the same time. - Sometimes the login is lost and the employee does not appear in the employees panel. - The employee is still disconnected after reloading the page. Desired behavior after PR is merged: - The login is awaited, so both requests are sent one after the other. - The employee is always connected and appears in the employees panel. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix stops non-product display lines from being linked to manufacturing stock moves. It helps keep sales, manufacturing, and inventory records accurate by preventing inappropriate sales order line selections during manufacturing order confirmation.
Original PR description
Issue: ====== before this commit, user was able to select a display SOL and at MO confirmation the SOL was copied to the stock move, so we end up with a stock move linked to a display SOL, which is not correct. Solution: ========= - add a domain on the SOL field as first guard layer - add check on the SOL on MO confirmation to prevent copying a display SOL to the stock move opw-6473017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a VAT validation issue where a child contact could keep an incorrect invalid status when processed before its parent company. Parent companies are now validated first, so related contacts correctly reuse the latest validation result and businesses avoid misleading VAT compliance information.
Original PR description
**Description of the issue/feature this PR addresses:** When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to…
**Description of the issue/feature this PR addresses:**
When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to be iterated before its parent, the child ends up with `vies_valid=False` instead of the parent's real, freshly-checked value.
**Current behavior before PR:**
`_compute_vies_valid` loops over `self` in whatever order the batch happens to have:
```python
for partner in self:
...
if partner.parent_id and partner.parent_id.vies_vat_to_check == partner.vies_vat_to_check:
partner.vies_valid = partner.parent_id.vies_valid
continue
status = partner._check_vies_iap()
partner._update_vies_status(status)
```
`Field.compute_value()` removes the whole batch from the "to compute" queue *before* running this loop (it does so upfront, in case the method does not assign every record). So when the loop reaches a child and reads `partner.parent_id.vies_valid` to reuse it, that field is no longer marked "to compute" for the parent, and reading it just returns whatever is currently cached/stored — which, if the parent has not been processed yet in this same loop, is still the old/default value. The child copies that stale value and, being a stored field, keeps it forever: nothing re-triggers its computation afterwards.
Example:
```python
parent = env['res.partner'].create({'name': 'Parent Co'})
child = env['res.partner'].create({'name': 'Child Address', 'parent_id': parent.id})
child.vat = 'BE0477472701' # queues the child's compute first
parent.vat = 'BE0477472701' # queues the parent's compute second
child.vies_valid # False, even though the VAT is valid
parent.vies_valid # True
```
**Desired behavior after PR is merged:**
Every partner without a parent is always computed before any child that may reuse its value, regardless of the batch's original order — so the child correctly ends up with the parent's real `vies_valid`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix prevents keyboard shortcuts such as Ctrl+B from changing text in areas that are not meant to support rich formatting, such as certain blog header or footer fields. It keeps the editor behavior consistent with the disabled toolbar and helps avoid accidental formatting changes in restricted content areas.
Original PR description
Problem: Selecting text in non-html fields disables toolbar formatting, but pressing CTRL+B still formats the text. Cause: `formatSelection` did not check if the selection was inside a non-html field before applying formats. Solution: Return early in `formatSelection` if the selection is inside a non-html model field element. Steps to reproduce: 1. Go to /blog and open an article. 2. Open editor and select header/footer text. 3. Press CTRL+B. => Selected text becomes bold. opw-6537402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Generated serial and lot numbers on receipts now automatically receive the product's default expiration date when expiration tracking is enabled. This prevents missing shelf-life information while preserving any expiration dates users already entered or imported.
Original PR description
**Issue** The expiration date is left blank when generating serial/lot numbers on a sml in a receipt, instead of being set from the product's default expiration settings. **Steps to reproduce** -…
**Issue** The expiration date is left blank when generating serial/lot numbers on a sml in a receipt, instead of being set from the product's default expiration settings. **Steps to reproduce** - Create a product tracked by SN, with Inventory > Traceability > Expiration Date enabled and an expiration time set. - Create and confirm a PO for that product. - Go to the receipt, open the Detailed Operations popup, and use "Generate Serials/Lots". -> The expiration date is not set on the generated serial/lot. **Cause** While generating the serial number, `action_generate_lot_line_vals` is called: https://github.com/odoo/odoo/blob/5d5f5381c27f67a8655a1c18bf1802c877d4cae2/addons/stock/models/stock_move.py#L1008 But it makes no reference to `expiration_date`. Moreover, it does not call `_compute_expiration_date` yet, before the save is performed: https://github.com/odoo/odoo/blob/5d5f5381c27f67a8655a1c18bf1802c877d4cae2/addons/product_expiry/models/stock_move_line.py#L38-L40 **Solution** Backport the fix from 19.0: https://github.com/odoo/odoo/commit/4f339301179c93a8bd48c55e3c54923c4698861a together with its follow-up, which avoids overwriting an expiration date already provided by a pasted import: https://github.com/odoo/odoo/commit/d0e0785c2fe63b6b7984432f5d0cdd73d4ca72ef opw-6417108
This fix prevents an extra SEPA Direct Debit XML field from being added for countries where banks may reject it, such as Italy. The field is now limited to Nordea-related countries that require it, improving payment file compatibility while preserving the original Nordea support.
Original PR description
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause: https://github.com/odoo/enterprise/commit/3c3c64b511d07fc1ba33c30363972f5b0f7283d6 added `<SchmeNm><Cd>CUST</Cd></SchmeNm>` unconditionally for all countries The original fix was intended for Nordea (Sweden) only, which requires this node explicitly The assumption that other countries would accept it was incorrect ### Steps to reproduce: - Install `account_sepa_direct_debit` and `l10n_it` - Switch to the IT company - In Settings, set SEPA Direct Debit Creditor Identifier to `BE30ZZZ300D000000042` - Create and confirm a Payment (Method: SEPA Direct Debit, any customer and amount) - Create and validate a Batch Payment with that payment - Open the generated PAIN008 XML Before the fix, `<SchmeNm><Cd>CUST</Cd></SchmeNm>` is present opw-6530996
This update makes an internal time-off test use fixed dates instead of dates based on when the test runs. It helps prevent false failures in automated checks, improving reliability without changing how users request or approve time off.
Original PR description
## Before: The test relied on relative dates (today + 2 days) when creating a leave request. The behavior depended on the day it was executed. For example, if the test ran on a Friday, the leave request would be created for Sunday, causing the validation to fail because the employee was not supposed to work on that day. ## After: This uses a static date for both the accrual allocation and creating the leave to avoid unnecessary errors. runbot-945745
This fix ensures the alternative writing mode choices in the AI Copywriter dialog appear in the user's selected language. It improves usability for multilingual users by removing untranslated labels from the editing experience.
Original PR description
Description of the issue/feature this PR addresses: The alternativemodes on the AI Copywriter dialog are not translated Current behavior before PR: <img width="1079" height="250" alt="image" src="https://github.com/user-attachments/assets/fced9432-b557-44de-9b7c-a31547b7a16b" /> Desired behavior after PR is merged: <img width="1078" height="250" alt="image" src="https://github.com/user-attachments/assets/1499836a-924e-425c-b328-27a378eae62a" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Final invoices now correctly show the remaining downpayment amount when a downpayment has been partially refunded through a credit note. French electronic invoicing via PDP also uses the correct document types and references for downpayments and related credit notes, helping businesses send compliant invoices.
Original PR description
## Bug n°1 (sale) Downpayment lines don't appear on the final invoice, when there is a credit note linked to the downpayment, even if the resulting downpayment is not zero. **STEP TO REPRODUCE** 1.…
## Bug n°1 (sale) Downpayment lines don't appear on the final invoice, when there is a credit note linked to the downpayment, even if the resulting downpayment is not zero. **STEP TO REPRODUCE** 1. Create a SO. 2. Create a downpayment (let's say 100$). 3. On this downpayment create a credit note, and set the downpayment line on the credit note to 50$. 4. Return to the SO, and create the final invoice. 5. On the final invoice, there is no mention of the downpayment and credit note. Expected behavior: The final invoice contains a downpayment line with a unit price of 100$ - 50$ = 50$. **CAUSE** We invoice the downpayment line 1 time for the downpayment, and 1 time for the credit note. This make qty_to_invoice computed on the downpayment line equal to 0, so it's skipped in the final invoice. **FIX** For downpayment line, we ignore the qty_to_invoice, and check if the price_unit of the downpayment line is not 0. If so, we should invoice the downpayment line. For final invoice, the invoiced qty should be -1, and 1 for downpayments and downpayment credit notes. ## Bug n°2 (l10n_fr_pdp) Odoo doesn't correcly handle downpayments when sending invoices using pdp. 1. Because of bug n°1, since downpayment lines don't appear on the final invoice when there is a credit note on the downpayment, the downpayment lines also don't appear in the generated xml. 2. For downpayment, the InvoiceTypeCode should be 386. For credit note of downpayment, the CreditNoteTypeCode should be 503. For the final invoice (invoice done after downpayments), the ProfileID should be B4. 3. On the final invoice, their should be BillingReference for each downpayments and credit note of those downpayments. With a corresponding DocumentTypeCode (386 downpayments, 503 credit notes). On import, there is 2 cases to handles for the final invoice. 1st case: the downpayments lines are present in the final invoice. (already handled by default) 2nd case: the downpayments line are not present in the final invoice. The downpayment amount is in the prepaidAmount node, and all amounts on the xml correspond to the invoice without any downpayments. In the 2nd case, we need to find the downpayments, and copy their lines to the final invoice. **STEP TO REPRODUCE** 1. Create a sale order. 2. Create a downpayment. 3. Create the final invoice and send it via pdp. 5. Inspect the xml and notice the requirements stated previously are not met. opw-6420924
Payment complement XML for Mexican electronic invoicing now aligns tax totals with their detailed lines, preventing PAC rejection caused by tiny rounding differences. This helps users successfully stamp partial payments across invoices with complex pricing without changing accounting ledger values.
Original PR description
Behavior before: Stamping payment complements fails with PAC validation error CRP20274 when partial payments reconcile across invoices with multi-decimal unit prices. Behavior after: Payment CFDI XML…
Behavior before: Stamping payment complements fails with PAC validation error CRP20274 when partial payments reconcile across invoices with multi-decimal unit prices. Behavior after: Payment CFDI XML generates and stamps successfully. Summary tax fields (ImporteP / BaseP) automatically align with the sum of child lines (ImporteDR / BaseDR), satisfying SAT validation rules without affecting financial ledgers. Root Cause: Invoice lines derived from dynamic pricelists, tax-inclusive pricing, or currency conversions store unit prices as 14-decimal floating-point numbers in account_move_line.price_unit (e.g., 38.19628647214854). During _l10n_mx_edi_add_payment_cfdi_values: 1. Child Document Lines (TrasladoDR): Odoo computes line tax amounts, applies percentage paid, and rounds to 6 decimal places per line (171.708217 + 186.628646 = 358.336863). 2. Payment Summary Total (TrasladoP): Odoo sums unrounded 14-decimal floats across all lines first, then rounds to 6 decimals at the end (358.336864). Because SAT rule CRP20274 requires ImporteP to equal sum of ImporteDR, this 0.000001 floating-point drift triggers a hard rejection. Fix: In _l10n_mx_edi_add_payment_cfdi_values(), added an explicit check that calculates the sum of pre-rounded child line values (dr_base_sum / dr_importe_sum). If a sub-cent discrepancy (< 0.01) exists between the summary total and the child line sum, p_tax['base'] and p_tax['importe'] are overridden to equal the exact sum of child lines. Steps to Reproduce: 1. Create a customer invoice where unit prices carry extended decimal precision (e.g., 38.19628647214854 from tax-inclusive pricing or 6-decimal pricelists) with multi-tax rules applied (IVA 16% + IEPS 30%). 2. Create a second similar PPD invoice for the same customer. 3. Register a single partial payment that reconciles across both invoices. 4. Attempt to process/generate the Payment CFDI XML. 5. Observe error CRP20274 (or CRP20273 for BaseP) returned by the PAC validator. opw-6480236
Fixes an issue where one task that could not be scheduled could incorrectly affect other tasks assigned to the same person. Project schedules now place each dependent task based on its own availability, reducing unexpected delays in Gantt planning.
Original PR description
Steps to reproduce: 1. create three tasks A,B & C with the same assignee 2. make tasks B and C depend on A and start on the `date_deadline` of task A 3. set the duration of task B (processed before C) to be longer than the 53-week search window 4. reschedule task A to end after task C starts Problem: A candidate that couldn't be scheduled was putting its assignee in conflict, subtracting the inspected availability while failing from the shared pool. Consequently, every later candidate sharing that assignee got force-placed into the same forward reschedule fallback that lands near the tail of the 53-week search window instead of the next available slot. Solution: Each candidate should be evaluated on its own ability to fit, and the time it occupies should count against the shared pool. opw-6380163 ---