Wednesday, July 22, 2026
16 changes · saas-19.3
Enhancements to existing features
Belgian POS setups can now adjust or request their POS ID until the blackbox has actually been used in a session. After first use, the POS ID is locked and the request option is hidden to help prevent changes to an active certified setup.
Original PR description
Add a `use_blackbox` computed field on `pos.config` (True as soon as any session uses the blackbox). The POS ID field becomes editable and the "Request POS ID" button is shown only while no blackbox has been used; once it has, the POS ID is locked and the button hidden. FW of: https://github.com/odoo/enterprise/pull/124965
Event staff can now print attendee badges in A4 PDF format directly from the registration desk. The same badge printing option is also available through Point of Sale, supporting smoother on-site operations for events such as OXP in Kenya.
Original PR description
This PR adds the support for A4 pdf badge printing through the registration desk. Requested for OXP in Kenya See https://github.com/odoo/odoo/pull/275021 Forward-Port-Of: odoo/enterprise#123478
Resolved issues and error corrections
This fix stops users from creating or editing WhatsApp templates from the event communication flow, where choosing the wrong template model could later make the communication line inaccessible. This protects event organizers from broken WhatsApp communications while respecting the stricter approval process required for WhatsApp templates.
Original PR description
Issue: User goes to Event.event Form -> communication tab -> add line Select whatsapp -> type something -> create and edit -> create new template with any model event.registration -> save ( all the way including the event form) reload page -> whatsapp event.mail displays "User does not have access to this record". Fix: add a patch to the js get m2oProps to deactivate edit, and create on the prop. WA Templates need more limitations for creation and edits due to the approval process from META's external API. We cannot block the full creation and edit in the xml becuase other event.mail types rely on that flow to create their types like social posts. This was a fix implemented due to needing to revert the oginal fix odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b opw-6334168 Forward-Port-Of: odoo/enterprise#124156 Forward-Port-Of: odoo/enterprise#121852
This fixes Peruvian electronic invoices so detraction withholding amounts are correctly converted to Peruvian soles when the company currency is not PEN. It prevents incorrect XML submissions to SUNAT and ensures PDF reports show the correct currency symbol.
Original PR description
**Steps to reproduce:** * Install the **l10n_pe_edi** module. * Change the company currency to **USD**. * Configure **Peruvian detraction** settings: * Set a **withholding percentage** on a product.…
**Steps to reproduce:**
* Install the **l10n_pe_edi** module.
* Change the company currency to **USD**.
* Configure **Peruvian detraction** settings:
* Set a **withholding percentage** on a product.
* Set a **withholding code** on the same product.
* Create a customer invoice in **USD**.
* Set the **Operation Type** to **[1001] Operation Subject to Detraction**.
* Add the configured product to the invoice.
* Confirm the invoice, **send it to SUNAT** by *process now**, and generate the ZIP which has XML.
**Observed behavior:**
* The generated XML contains: `<cbc:Amount currencyID="PEN">116.82</cbc:Amount>` The `currencyID` is `PEN` but the amount is the raw USD value instead of being converted to PEN using the exchange rate.
* The PDF report also shows the withholding amount with the wrong currency symbol.
**Cause:**
* `_l10n_pe_edi_get_spot()` computed `spot['amount']` as `amount_total_signed * percent`, where `amount_total_signed` is stored in the **company currency**. When the company currency is PEN this works correctly, but when it is changed to USD the value is in USD while the XML node hardcodes `currencyID="PEN"`.
* `spot['currency']` was also set to `company_id.currency_id`, so the PDF rendered the amount with the wrong currency symbol.
* In `_add_invoice_payment_terms_nodes`, `spot_amount` was selected via `spot['amount'] if invoice.currency_id == invoice.company_id.currency_id` which relied on company currency being PEN as a proxy for the invoice being in PEN, breaking when company currency is USD.
**Fix:**
* In `_l10n_pe_edi_get_spot()`, compute `spot['amount']` by explicitly converting `amount_total` from the invoice currency to PEN using `currency_id._convert(..., env.ref('base.PEN'), ...)`, ensuring the detraction amount is always in PEN regardless of the company currency.
* Set `spot['currency']` to `env.ref('base.PEN')` so the PDF report always displays the withholding amount with the correct PEN symbol.
* In `_add_invoice_payment_terms_nodes`, always use `spot['spot_amount']` (invoice currency amount) for the `FormaPago`/`Cuota` arithmetic, since `spot['amount']` is now exclusively the PEN amount for the detraction XML node.
opw-6327571
Forward-Port-Of: odoo/enterprise#125063
Forward-Port-Of: odoo/enterprise#123782UPS international shipments now use the proper customer address on commercial invoices when billing and delivery addresses differ. If UPS requires the sold-to country to match the delivery country, the system falls back to the delivery address and warns the user, helping avoid failed shipments.
Original PR description
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- -…
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- - Create a belgian company - Setup UPS - Create a French customer - Add a different french delivery address - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > Commercial invoice `Sold To` uses the delivery address Solution for case 1 ----- Use the delivery address' `commercial_partner_id`. This leads to another issue in some edge cases... Problematic case 2 (caused by case 1 fix) ----- - Create a belgian company - Setup UPS - Create a French customer - Add a delivery address in Switzerland - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > UPS error `The Sold To party's country code must be the same as the Ship To party's country code with the exception of Canada and satellite countries.` Solution for case 2 ----- Default back to delivery address for the `Sold To` field when countries don't match, as this is a limitation of the UPS API. Warn the user, either on the SO or the transfer itself (if no SO). Warning looks like this (on SO): <img width="1914" height="716" alt="image" src="https://github.com/user-attachments/assets/f7aa73c4-f24c-42da-8f3e-6a58765ef020" /> ----- Ticket: opw-6200263 Forward-Port-Of: odoo/enterprise#121479 Forward-Port-Of: odoo/enterprise#118031
The report discussion panel now remains visible at the right side of the screen even when financial reports are very wide. This makes it easier for users to communicate and collaborate without needing to scroll horizontally across large reports.
Original PR description
Issue: - When reports are large/wide, the chatter component is pushed beyond the visible viewport, appearing only at the absolute right edge of the overflowing report rather than the right edge of the screen. Fix: - Updated the layout container to prevent the chatter from shrinking or overflowing with the report block, ensuring the main report scrolls independently while the chatter stays pinned to the screen viewport. Impact: - Keeps the chatter panel fully visible on the right side of the screen, allowing users to communicate without scrolling horizontally on wide reports. task-[6376792](https://www.odoo.com/odoo/project/967/tasks/6376792) Forward-Port-Of: odoo/enterprise#125055 Forward-Port-Of: odoo/enterprise#123734
Spanish VAT books now correctly show tax amounts for vendor bills using taxes with negative components, such as certain EU purchase taxes. This prevents valid tax amounts from being displayed as zero, improving accuracy in Spanish VAT reporting.
Original PR description
Problem: In the Spanish VAT books, taxes with negative component (like 21% EU G) always show their amounts as zero. Steps to reproduce: 1. Install the l10n_es_reports module and select the Spanish company 2. Create a vendor bill with a vendor from another EU country and add a product 3. Make sure the tax applied to the product has a negative component (like 21% EU G) 4. Confirm the bill 5. Go to Accounting > Reporting > Tax Return 6. Generate the VAT books from the action menu and check the tax amounts 7. Notice how the tax amount is zero, even though the tax was applied to the bill Cause: When calculating the tax amounts, the negative component cancels out the positive component, leading to the amount always showing as zero in the VAT books. opw-6169766 Forward-Port-Of: odoo/enterprise#124030 Forward-Port-Of: odoo/enterprise#123738
Creating or viewing Australian payroll super accounts could trigger an error due to inconsistent internal handling of employee data. This fix keeps that handling consistent, helping payroll administrators complete super account setup without interruption.
Original PR description
Version - 19.0 Steps to reproduce(runbot): - Install `l10n_au_hr_payroll` - Go to Payroll -> Configuration -> Super Accounts - Create a Super Account by filling all the required fields - You will…
Version - 19.0
Steps to reproduce(runbot):
- Install `l10n_au_hr_payroll`
- Go to Payroll -> Configuration -> Super Accounts
- Create a Super Account by filling all the required fields
- You will encounter the issue
**TraceBack:**
```
('hr.menu_hr_employee_payroll', 485, 'Employees > Employees', 756):
Traceback (most recent call last):
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 346, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 377, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 537, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 570, in mock_view_form
[data] = record.read(fields_list)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3490, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3747, in _read_format
vals[name] = convert(record[name], record, use_display_name)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 6688, in __getitem__
return self._fields[key].__get__(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1744, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1915, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/19.0/addons/mail/models/mail_thread.py", line 484, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 4954, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/enterprise/19.0/l10n_au_hr_payroll/models/hr_employee.py", line 118, in _compute_proportion_warnings
proportions[emp.id] * 100,
KeyError: 4
```
Issue:
During the refactoring from `read_group()` to `_read_group()`, the `proportions` dictionary became keyed by `hr.employee` records instead of employee IDs. While the condition was updated to use `proportions.get(emp)`, the warning message still accessed the dictionary using `proportions[emp.id]`, resulting in a `KeyError`.
Fix:
Use the employee record consistently when accessing the `proportions` dictionary after switching to `_read_group()`.
Task ID - 6390373
Refrence:
https://github.com/odoo/enterprise/pull/72217/changes#diff-8ae3564d54e47eec919ef273d44f6276d8c6df60e21c5c8c8f7292b1c38cf541R460
Forward-Port-Of: odoo/enterprise#124478Email buttons for appointments now use the website tied to the appointment setup, even when users have interacted with another website. This prevents customers from being sent to the wrong site when viewing or managing their appointment.
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from…
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. Case 1: - Have website A and website B - Create an appointment page website A - Log in via website B - As public user, make an appointment in Website A - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the appointment. This occurs because when an user log in, the system parameter 'web.base_url' is updated with the current url. This parameter is then used as fallback when we need to retrieve the base url without an active record Case 2: - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) Backport with improvements of 15bae202d8f1b5bf70bbc63b2d89025e9237e6cf opw-4146760 opw-4336369 Forward-Port-Of: odoo/enterprise#124714 Forward-Port-Of: odoo/enterprise#122669
This fix prevents database upgrades from failing when a predefined HR employee documents folder was previously deleted or deactivated. The upgrade now skips unavailable folders when adding the HR Sign action, helping customers complete upgrades without manual recovery steps.
Original PR description
Steps to reproduce: 1 Install documents_hr and hr_sign on saas-19.1. 2 Go to Settings → Documents → disable Human Resources. 3 Open the Documents app and delete the Employees - My Company folder. 4…
Steps to reproduce:
1 Install documents_hr and hr_sign on saas-19.1.
2 Go to Settings → Documents → disable Human Resources.
3 Open the Documents app and delete the Employees - My Company folder.
4 Upgrade the database to saas-19.2.
Issue:
- During the upgrade, the post-init hook attempts to embed the HR Sign action into predefined document folders. Since the Employees - My Company folder has been deleted (or is inactive), the folder lookup returns no record, leading to the following error:
```python3
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-19.2/odoo/service/server.py", line 1664, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/func.py", line 65, in locked
return func(inst, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/registry.py", line 186, in new
load_modules(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 465, in load_modules
load_module_graph(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 244, in load_module_graph
getattr(py_module, post_init)(env)
File "/home/odoo/src/enterprise/saas-19.2/documents_hr_sign/__init__.py", line 12, in _embed_sign_post_init
folders.with_user(SUPERUSER_ID)._embed_action(sign_action.id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1643, in _embed_action
folder.action_folder_embed_action(folder.id, action_id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1614, in action_folder_embed_action
return self.get_documents_actions(folder_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1522, in get_documents_actions
raise UserError(_('This folder does not exist or is not accessible.'))
odoo.exceptions.UserError: Esta carpeta no existe o no es accesible.
```
Root cause:
- As part of documents_sign, the documents_hr_sign action is embedded into predefined document folders (introduced in https://github.com/odoo/enterprise/pull/101890).
- The folder lookup relies on [_search()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L4681-L4691), which filters out inactive records
through the active test. Consequently, [search_fetch()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L1441-L1451) returns no matching
folder when the predefined folder has been deleted or deactivated. It will
try to get document actions of predefined folder here, so if the folder is
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1592
inactive it will not be able to read the folder here.
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1494
Fix:
- Instead of attempting to embed the Sign action into all company employee folders, filter out inactive folders before calling _embed_action().
- This ensures the post-init hook only processes active employee document folders. If a predefined folder has been deleted or deactivated, it is skipped preventing the upgrade from attempting to embed an action into an inaccessible folder and avoiding the resulting UserError.
opw-6358063
upg-4449902
Forward-Port-Of: odoo/enterprise#123846Adds a default limit on how many reusable packages are loaded when opening transfers in the Barcode app. This prevents very long loading times for companies with tens of thousands of packages, improving usability without requiring manual configuration.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730 Forward-Port-Of: odoo/enterprise#124538 Forward-Port-Of: odoo/enterprise#123696
Envia shipping labels for Amazon now include each product's weight in the shipment details. This prevents label validation failures for orders with larger quantities, reducing blocked deliveries for affected customers.
Original PR description
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight…
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight exceeds package weight. Please refer to API documentation for allowable limits. (D-703)` Even though the [Envia documentation](https://docs.envia.com/reference/create-shipping-label) doesn't include it, it seems that Amazon requires the weight for each product. If the payload doesn't include the per-item weight, Amazon will set a default weight, which will cause the error to show up if the delivery contains a high quantity. This can be a blocking issue for some customers. **Steps to reproduce on a fresh DB:** - Install Inventory, Sales, and Envia Shipping - Switch company to be based in India (need to provide an address to deliver from, I just used the Odoo India address - InfoCity Gate, Gandhinagar, Gujarat 382007) - Configure an Amazon delivery carrier with Envia (India seems to be the only country that supports Amazon with Envia) - Inventory > Configuration > Delivery Methods > Envia.com method - Must be in a Production environment (because Envia's sandbox server does not work for some reason?) - Add an Envia Production Access Token (will have to use one with some funds) - Change 'Ship From' to India - Configure the `Envia.com Service Name`, set Carrier and Service to AMAZON and AMAZON - Amazon Shipping Standard - Create a demo product, give it an arbitrary weight like 0.1 kg - Create a sales order to an Indian customer, include the demo product with a high quantity (like 20), confirm (might have to create a warehouse and configure the customer's information) - On the generated picking, set the Carrier to Envia.com on the Additional Info tab - When trying to Validate, it should throw the error **Fix:** When generating the payload in _get_shipping_lines() in envia_request, include the item weight in the dictionary. Related ticket: opw-6261682 Forward-Port-Of: odoo/enterprise#125017 Forward-Port-Of: odoo/enterprise#123935
The AI assistant now treats database rule violations during record creation or updates as recoverable errors, allowing it to retry instead of failing completely. It also improves access to certain internal model information needed for valid record creation, making AI-driven workflows more dependable for users.
Original PR description
Prior to this commit, the create and update tool calls could cause an unrecoverable error if the model tried to use values which were causing an SQL constraint to fail. With this commit, we add a try..except block with a savepoint to treat the SQL constraint errors as regular errors, ensuring that the model is able to retry if it misses a check. task-6196137
Map views now continue to open even when the optional company address location lookup cannot be completed. This prevents users from being blocked by an external map service failure and lets them keep working without the estimated starting position.
Original PR description
Since the introduction of the user position fetch, opening a map view with no user position available geocodes the company address through OSM during `onWillStart`, without any error handling: if the request fails, the whole view crashes. Geocoding the user position is best-effort: on failure, load the view without it, this is consistent with the other OSM call sites. runbot-error-242047
This fixes an issue where some Balance Sheet lines could miss prior-year accounting entries after a company lock date was set. Reports that rely on stored snapshots now use the correct cutoff date, helping ensure financial figures remain complete and reliable over time.
Original PR description
Issue: After a lock date is set on a company, certain lines on the Balance Sheet report that look back before a given date, such as "Profits (Losses) from Previous Years", can end up silently missing…
Issue: After a lock date is set on a company, certain lines on the Balance Sheet report that look back before a given date, such as "Profits (Losses) from Previous Years", can end up silently missing data. Steps to reproduce: 1. Create a company located in Belgium. 2. Create an invoice. Give it a date in 2025. 3. Go to the Balance Sheet (Abbr Con) (BE) report. Observe that the value on the newly created invoice is captured in the line: "Profits (Losses) from Previous Years". 4. Set a lock date for Dec. 31st, 2025. 5. Return to the same Balance Sheet. Observe that the "Profits (Losses) from Previous Years" is now 0. Note: The issue isn't caused by anything in the Belgium localization. However, not all Balance Sheets have a line that both looks back before a given date and also gets captured in snapshots. The Balance Sheet (Abbr Con) (BE) report has such a line. Explanation: When a lock date is set to Dec. 31st 2025, snapshots are created. The snapshots' `date` fields are all set to Dec. 31st 2025, matching the lock date. One snapshot--responsible for the line "Profits (Losses) from Previous Years"--will have a `date_scope` of `to_beginning_of_fiscalyear`. In that snapshot, the data actually aggregated only covers up to the end of the prior fiscal year, Dec. 31st 2024. So the snapshot's `date` doesn't match its own data's real cutoff. When the report is generated, to calculate the line "Profits (Losses) from Previous Years", Odoo sums only the entries dated after the snapshot's `date`. Odoo then adds that to the snapshot's stored figure. This becomes an issue if the report is viewed as of a date in 2026. As of 2026, the line should include all 2025's entries. But, these entries will not be included. They aren't part of the snapshot, and they're skipped again since summing only resumes after Dec. 31st, 2025. A similar problem will arise in any report lines that both get captured in a snapshot and also use a `date_scope` that cuts off before the report's as of date. Solution: We now set the `date` field of snapshots to the data's real cutoff, instead of the lock date. We get the data's real cutoff from `_get_date_bounds_info`, which is the same method used to build the query that searches for the account move lines to include in the snapshot. This way, the snapshot's `date` always matches the data it actually contains. Note: snapshots created before this fix may still hold a mismatched `date` and should be regenerated. opw-6379956
Belgian POS receipts now show the VAT rate actually applied after a fiscal position changes the tax. This prevents mismatches between the POS sale and the fiscal device receipt, improving tax accuracy for affected transactions.
Original PR description
Steps to reproduce: =================== - Configure a product with a 12% VAT - Create a fiscal position that maps 12% → 6% - Open POS and apply the fiscal position to an order - Add the product and…
Steps to reproduce: =================== - Configure a product with a 12% VAT - Create a fiscal position that maps 12% → 6% - Open POS and apply the fiscal position to an order - Add the product and validate the sale - Download Receipt Issue: ====== - The POS correctly applies and displays the mapped 6% VAT - The payload sent to the FDM still uses the product's original 12% VAT - As a result, the receipt displays the wrong VAT rate Cause: ====== - VAT labels in the Blackbox payload were generated from product_id.taxes_id - Fiscal position tax mappings were ignored when building VAT inputs - Blackbox product prices were also computed without taking the fiscal position into account Fix: ==== - Use taxes after fiscal position mapping when generating VAT data for the Blackbox payload - Ensure VAT labels sent to the FDM match the taxes applied on the POS order - Apply fiscal position tax mapping when computing Blackbox product prices Task:6392006 FW of : https://github.com/odoo/enterprise/pull/124975