Friday, July 11, 2025
11 changes · saas-18.1
Resolved issues and error corrections
Turkish Nilvera e-invoice XML notes now include the outstanding amount written in uppercase words, helping recipients read and verify invoice totals more clearly. For invoices in a foreign currency, the note includes both the Turkish lira amount and the original currency amount, including correct wording when whole or fractional parts are zero.
Original PR description
This commit will add the amount residual in text in the note of the xml we sent to nilvera. If the invoice is in another currency than Turkish Lira, we have to add two notes one for the amount in turkish lira and one in the other currency task-4518269 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217910 Forward-Port-Of: odoo/odoo#195938
Cash-rounded invoices now export valid UBL electronic invoice files with totals, taxes, and payable amounts aligned. Imports of these electronic invoices also better recreate the original invoice, reducing validation failures and accounting discrepancies for businesses using cash rounding.
Original PR description
Currently these problems can appear when an invoice is cash rounded. 1. In case we use the "Modify tax amount" (`biggest_tax`) cash rounding strategy: The rounding amount is added to the taxes in…
Currently these problems can appear when an invoice is cash rounded.
1. In case we use the "Modify tax amount" (`biggest_tax`) cash rounding strategy:
The rounding amount is added to the taxes in Odoo but not in the UBL XML
- This affects everything that uses `_prepare_invoice_aggregated_taxes`
(and not just UBL XML)
2. The generated UBL XML is invalid (for any rounding strategy).
See below for details.
3. The import of the exported UBL XML does not yield back the same invoice
(even after fixing the export / the previous 2 problems).
Also there are some problems with the correction of tax values
of imported UBL XML (`correct_invoice_tax_amount`).
(They probably do not cause issues in practice but would after this
fix. We adapt the correction as part of the fix for (3).)
#### Runbot: How to generate problematic XML
1. Select BE Company CoA
2. Enable Cash Rounding in the settings
3. Create a cash rounding method
(in the settings where cash rounding can be enabled):
- precision `1.00`
- strategy: any
- profit / loss account: any
4. Create an invoice
- Set a Belgian partner (e.g. "BE Company CoA" is okay)
- Set the the cash rounding method from step 2
- Single Line with price=70.00€ and a 21% tax
5. The total should be 85.00 € (84.70 € w/o the rounding)
In the journal items there should be the following
non payment term items:
- 70.00€ base
- 14.70€ tax
- 0.30€ rounding (depending on the cash rounding strategy the tax is set or not)
6. Confirm & Send (with BIS Billing 3.0)
7. Look at the UBL BIS 3 XML in the `Invoice` element
- `TaxTotal/TaxAmount`: 14.70€
- `TaxTotal/TaxSubtotal/TaxableAmount`: 70.00€
- `TaxTotal/TaxSubtotal/TaxAmount`: 14.70€
- `LegalMonetaryTotal/TaxExclusiveAmount`: 70.00€
- `LegalMonetaryTotal/TaxInclusiveAmount`: 85.00€
- `LegalMonetaryTotal/PayableAmount`: 85.00€
8. This fails validation `BR-CO-15`:
```
Invoice total amount with VAT (BT-112)
= Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).
```
(`LegalMonetaryTotal/TaxInclusiveAmount` = `LegalMonetaryTotal/TaxExclusiveAmount` + `TaxTotal/TaxAmount`)
Since the cash rounding is included in `LegalMonetaryTotal/TaxInclusiveAmount` but not in
`TaxTotal/TaxAmount` (or `LegalMonetaryTotal/TaxExclusiveAmount`)
#### Tax value correction details (with examples)
Currently we try to fix the tax amounts after importing an invoice.
The function we use for that (`_correct_invoice_tax_amount`) has the following issues:
- We look for `TaxTotal/TaxSubtotal` elements anywhere.
But i.e. such elements can also exist inside `InvoiceLine` elements.
Example:
- module `l10n_dk_oioubl` file `test_xml_oioubl_dk.py`
- function `test_oioubl_import_exemple_file_4` / XML file 'external/BASPRO_01_01_00_Invoice_v2p1.xml'
- The tax total parsed from the document may need to be inverted.
E.g. credit notes can be given as an invoice with negative amounts.
See function `_get_import_document_amount_sign`.
Example:
- module `l10n_account_edi_ubl_cii` file `test_xml_ubl_be.py`
- function `test_import_invoice_xml_open_peppol_examples` / XML file 'bis3_invoice_negative_amounts.xml'
- We compare the tax total from the document only with a single line of that tax.
But there can be multiple lines for a single tax. We have to use the sum of all those lines for the comparison.
Example:
- module `l10n_account_edi_ubl_cii` file `test_xml_ubl_au.py`
- function `test_export_import_invoice` / XML file 'from_odoo/a_nz_out_invoice.xml'
#### The fix
This commit does the following to fix that
1. We include cash rounding lines belonging to a tax in the tax computation for the UBL XML export
(or rather everything any tax computation done with `_prepare_invoice_aggregated_taxes`).
2. After fixing (1) we only have to fix the "Add a rounding line" (`add_invoice_line`) strategy.
This is as follows
- Subtract the cash rounding from the `LegalMonetaryTotal/TaxInclusiveAmount`
- Add node `LegalMonetaryTotal/PayableRoundingAmount` with the value of the cash rounding
3. Cases
- `add_invoice_line`: We create a dedicated invoice line with the amount found in node
`LegalMonetaryTotal/PayableRoundingAmount` (if it is present).
- `biggest_tax`: We update the amount on the tax line to match the value found in the XML.
(Currently we only do this if the difference is not greater than '0.05')
The fixes for the tax value correction on import are also needed for 3./`biggest_tax`.
#### Runbot: example XML after the fix
The export in the example then looks like this for the different cash rounding strategies
- `add_invoice_line`
- `TaxTotal/TaxAmount`: 14.70€
- `TaxTotal/TaxSubtotal/TaxableAmount`: 70.00€
- `TaxTotal/TaxSubtotal/TaxAmount`: 14.70€
- `LegalMonetaryTotal/TaxExclusiveAmount`: 70.00€
- `LegalMonetaryTotal/TaxInclusiveAmount`: 84.70€
- `LegalMonetaryTotal/PayableRoundingAmount`: 0.30€
- `LegalMonetaryTotal/PayableAmount`: 85.00€
The validation for the `LegalMonetaryTotal/PayableAmount` is still
okay since (in the example) it is just `LegalMonetaryTotal/TaxInclusiveAmount` + `LegalMonetaryTotal/PayableRoundingAmount`.
- `biggest_tax`
- `TaxTotal/TaxAmount`: 15.00€
- `TaxTotal/TaxSubtotal/TaxableAmount`: 70.00€
- `TaxTotal/TaxSubtotal/TaxAmount`: 15.00€
- `LegalMonetaryTotal/TaxExclusiveAmount`: 70.00€
- `LegalMonetaryTotal/TaxInclusiveAmount`: 85.00€
- `LegalMonetaryTotal/PayableRoundingAmount`: (not exported)
- `LegalMonetaryTotal/PayableAmount`: 85.00€
#### References
Also see
- https://docs.peppol.eu/poacc/billing/3.0/bis/#_rounding
- https://docs.peppol.eu/poacc/billing/3.0/bis/#_calculation_of_totals
task-4854592
Forward-Port-Of: odoo/odoo#217119
Forward-Port-Of: odoo/odoo#213378Windows-connected printers now process one print job at a time to avoid errors when several documents are printed simultaneously. This makes printing through IoT hardware more dependable during busy periods.
Original PR description
Before this commit, if multiple documents were sent to print at exactly the same time, some of them could end up erroring because the Windows printing API requires us to send one document at a time. After this commit, we use a lock similar to the Linux driver, to ensure that only one document is sent to the printer at once. opw-4829908 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218375 Forward-Port-Of: odoo/odoo#218300
Pasting multi-line content into the Odoo editor now removes invisible empty blocks and converts pasted sections into valid editor paragraphs. This prevents broken placeholder behavior and reduces unwanted formatting from external sources like chat apps.
Original PR description
Steps to Reproduce : - Open the Discord app - Copy the text written in multiple lines - Paste it in the Odoo Editor - Click below any line or empty space - You will notice that the placeholder "Type…
Steps to Reproduce : - Open the Discord app - Copy the text written in multiple lines - Paste it in the Odoo Editor - Click below any line or empty space - You will notice that the placeholder "Type '/' for commands" is getting destroyed. Description of the issue this PR addresses: - The issue was caused by visually empty `<div>` elements included in pasted content and not converted into baseContainer. - This regression was introduced in commit [#196481](https://github.com/odoo/odoo/pull/196481/files?diff=split&w=0#diff-1b8ed5b7d66a870806b1e7400a0d6cb9ba8810327824244eca868be9583b7fd9L467-L477), which stopped replacing blacklisted tags like `<div>` with `<p>`. - As a result, cleanForPaste no longer strips inline styles from `<div>` elements. Current behavior before PR: - Pasted content includes non-visible `<div>` elements. - These empty blocks occupy space without contributing visual content. - Inline styles from copied content remain intact. - `<div>` elements are not replaced with valid block tags. - Placeholder rendering is broken in these ghost spaces. Desired behavior after PR is merged: - Non-empty `<div>` elements are replaced with a baseContainer element. - Empty `<div>` elements are automatically removed from pasted content. - This restores the expected cleaning behavior, removes unwanted styles, and preserves line breaks. task-4805536 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#210797
This fix prevents an error when a canceled sales order containing a kit product is reset and confirmed again. It ensures canceled delivery movements are ignored and duplicate kit components are handled consistently, so users can continue their sales workflow without interruption.
Original PR description
Bug introduced in: https://github.com/odoo/odoo/pull/207955
Steps to reproduce the bug:
- Create a kit product:
- BoM:
- Components:
- 1 unit of C1
- 1 unit of C1 (same product)
- Create a SO with one unit of kit
- Confirm the SO
- The delivery is created
- Cancel the SO → the delivery is canceled.
- Set the SO back to quotation and confirm again
Problem:
A traceback is triggered:
raise ValueError("Expected singleton: %s" % record)
ValueError: Expected singleton: mrp.bom.line(24, 25)
When a kit's BoM contains the same product multiple times, multiple bom_line_ids match a given move. Assigning them causes an error. Additionally, cancelled moves were incorrectly considered.
Solution:
Filter out cancelled stock moves before accessing the bom_line_id to ensure only active moves are considered.
opw-4919875
Forward-Port-Of: odoo/odoo#218187Employees using working schedules in a different timezone could be checked out too early when their check-in date differed between UTC and their local schedule. The fix uses the employee schedule's local date so expected hours and previous attendance are calculated correctly.
Original PR description
**Issue** The auto check out cron was using the check in time in UTC to determine the excepted working hours and the previous attendances. For example: - have an employee with a working schedule using a UTC+8 timezone. - check-in on a monday before 8am (0:00 UTC) in the employee's tz. - the auto check-out cron closes the attendance immediately because there are no working hours for the attendance's check in day in UTC (Sunday). **Change** Use the date of the check-in localized in the tz of the calendar used by the attendance's employee to determine the previous worked hours for that day and the expected worked hours. opw-4654847 Forward-Port-Of: odoo/odoo#212594
This update refreshes the spreadsheet engine with fixes for pivot tables, date handling, row sizing, and demo actions. Users should see more accurate spreadsheet results and faster handling of imported Excel files, especially when working with pivot tables.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/3456a93e8 [REL] 18.1.29 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/3456a93e8 [REL] 18.1.29 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/a01097480 [PERF] pivot: don't invalidate cache needlessly [Task: 4933971](https://www.odoo.com/odoo/2328/tasks/4933971) https://github.com/odoo/o-spreadsheet/commit/33431cca5 [FIX] pivot: don't aggregate calculated missing value [Task: 4933818](https://www.odoo.com/odoo/2328/tasks/4933818) https://github.com/odoo/o-spreadsheet/commit/90f051bdf [FIX] Cells: newline is not a valid date separator [Task: 4910327](https://www.odoo.com/odoo/2328/tasks/4910327) https://github.com/odoo/o-spreadsheet/commit/7767e1a4c [PERF] import xlsx: avoid reading all cells multiple times during table_conversion [Task: 4699860](https://www.odoo.com/odoo/2328/tasks/4699860) https://github.com/odoo/o-spreadsheet/commit/3470767a7 [FIX] Config: remove eslint [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/ba9911767 [IMP] config: ignore .DS_Store file from mac os [](https://www.odoo.com/odoo/2328/tasks/) https://github.com/odoo/o-spreadsheet/commit/9fde8d70e [FIX] header_size: resize row based on link label instead of full link [Task: 4886598](https://www.odoo.com/odoo/2328/tasks/4886598) https://github.com/odoo/o-spreadsheet/commit/1c3f6435f [FIX] pivot: allow to group by error [Task: 4886041](https://www.odoo.com/odoo/2328/tasks/4886041) https://github.com/odoo/o-spreadsheet/commit/73297562f [FIX] demo: fix `clear` action again [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/a8368d244 [FIX] demo: Fix new `clear` action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) 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: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Mehdi Rachico (mera) <mera@odoo.com> Co-authored-by: Florian Damhaut (flda) <flda@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>
This fixes an issue where companies using Belgian 281.50 reporting could encounter an error when installing Inventory after generating a 325 form. The change adjusts company validation so valid shared contacts no longer block Inventory setup.
Original PR description
### Steps to reproduce: - Install l10n_be_reports & account_accountant. - Switch to "BE Company CoA" company. - Add "281.50" tag to "YourCompany" contact. - Accounting > Configuration > Accounting >…
### Steps to reproduce: - Install l10n_be_reports & account_accountant. - Switch to "BE Company CoA" company. - Add "281.50" tag to "YourCompany" contact. - Accounting > Configuration > Accounting > Chart of Accounts > Add "281.50 - Commissions" tag to 600000 account in CoA. - Create a Vendor Bill for partner "YourCompany" selling "[E-COM11]". Date it sometime in 2024 and confirm. - Go to Accounting > Reporting > Open 325 Forms. - Create a new form for 2024. - Verify that there is a line for "YourCompany" in the form and generate the XML. - Try to install Inventory. #### > Traceback due to a company inconsistencies. ### Cause of the issue: When creating the new `l10n_be.form.281.50` form for 2024, we create a record for "BE Company CoA" and which `partner_id` is the `res.partner` "YourCompany" which does not belong to any company (and hence is accessible from any). However, on the `forms_281_50` related field of the `res.partner` model is `check_company=True`: https://github.com/odoo/enterprise/blob/bc36a68b68c3d0296ee18c3a121b029dd418f430/l10n_be_reports/models/res_partner.py#L15-L23 Currently, this did not matter because we did no call of the `_check_company`. But if we where to launch a call of the `_check_company` on "YourCompany" `res.partner` we would raise a company error. Now, when you install stock 2 things happen and provoke this call: 1) The `res.partner` model becomes `_check_company_auto`: https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/addons/stock/models/res_partner.py#L8-L10 2) We create a warehouse for "Your company and update the `partner_data` https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/addons/stock/models/stock_warehouse.py#L143-L145 https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/addons/stock/models/stock_warehouse.py#L315 However, the `property_stock_customer` and `property_stock_supplier` are `check_company` related fields: https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/addons/stock/models/res_partner.py#L12-L17 Therefore, writing on them for a `_check_company_auto` record will launch a call of the `check_company` for all the fields of the record (including the already inconsistent `forms_281_50`): https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/odoo/models.py#L3780-L3781 https://github.com/odoo/odoo/blob/b7dbf15aa8116e51708bd51b8dda9bd12bba0a9e/odoo/models.py#L3867-L3868 ### Fix: We loosen the company check on the `forms_281_50` to not rely on the `_check_company` since the current workflow lead functionally to valid record data's that will always be considered invalid by this method. opw-4845434 Forward-Port-Of: odoo/enterprise#89590
Fixed an issue in Barcode deliveries where scanning a destination package after scanning products from multiple locations could incorrectly change earlier products to the last scanned source location. This helps ensure stock moves keep the correct origin location while still assigning products to the intended package.
Original PR description
Issue ===== When a package is scanned as the destination package, if a source location was previously scanned, the source location will be updated for every product who will be packed. How to…
Issue ===== When a package is scanned as the destination package, if a source location was previously scanned, the source location will be updated for every product who will be packed. How to reproduce ================ - Enable multi-locations and package; - Create an empty package, two locations and two products; - Create a delivery in the Barcode app; - Scan the first location then the first product; - Scan the second location then the second product; - Scan the empty package -> The package is rightly assigned as the result package for both lines, but the source location of the first product was update for the last scanned source location. Cause of the issue ================== When a source location was previously scanned, when a line is updated (`updateLine`), we update the line's source location. Usually, that's the wanted behavior but in this case, we don't want to the source location of already processed lines when we scan a destination package. Solution ======== When calling `updateLine` from `_assignEmptyPackage`, give a key in the parameters to not update the source location. [opw-4859851](https://www.odoo.com/odoo/project.task/4859851) Forward-Port-Of: odoo/enterprise#89422 Forward-Port-Of: odoo/enterprise#89142
Manufacturing orders created or opened in the barcode app now handle bill of materials line units correctly, even when unit-of-measure settings are disabled. This prevents errors and ensures component quantities are recorded using the intended units from the bill of materials.
Original PR description
Previous behaviour: * Traceback if MO created with a BoM whose lines have UoMs that don't correspond to those of the products, then UoM setting disabled and MO viewed in the barcode app. * BoM line UoMs ignored in favour of product UoMs when creating MO in the barcode app. New behaviour: * No traceback. * Stock moves in MOs properly created with the corresponding BoM line UoMs. Task ID: [4674196](https://www.odoo.com/odoo/my-tasks/4674196)
This update corrects how cash rounding is handled in Colombian electronic invoicing files. It helps ensure tax and rounding amounts are included correctly, reducing the risk of rejected or inaccurate electronic invoices.
Original PR description
#### [FIX] l10n_co_dian: UBL related cash rounding issues In the community PR the UBL XML generation was adjusted to support cash rounding. (See there for more details) This commit adjusts the code in `l10n_co_dian` to be compatible. #### [FIX] l10_co_edi: tax_amls include rounding lines Currently rounding lines (with taxes) are not included in the tax lines. This is fixed in this commit. See the community PR / commits for motivation. #### info task-4854592 Forward-Port-Of: odoo/enterprise#89439