Daily updates from Odoo
Saturday, June 27, 2026
4 changes
1 change
New functionality added to Odoo
This update adds support for Belgium’s certified cash register requirements in POS restaurant workflows. It ensures sales, refunds, cash movements, reports, and related actions are properly recorded and signed for fiscal compliance, including support for training mode and error handling. It also extends the solution to related flows such as employee clock-in/out, loyalty rewards, self-ordering, deferred payments, and online orders so they follow the same certified process.
Original PR description
Note: this PR is a forward of https://github.com/odoo/enterprise/pull/96130 Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance…
Note: this PR is a forward of https://github.com/odoo/enterprise/pull/96130 Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance for certified POS restaurant systems. The implementation is split into a core module and five bridge modules: l10n_be_pos_blackbox (main module): - FDM (Fiscal Data Module) communication layer that signs every fiscal event by sending a structured message to the blackbox device and receiving a hash + VSC counter in return. M110 (sale), M111 (refund), M112 (partial refund), M121 (order), M122 (cost-centre change), M123 (pre-bill), M130 (money in/out), M131 (drawer open), M140/M141 (work in/out), M150 (invoice), M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). - Input generator that encodes all line-level fiscal data (PLU hash, VAT groups, price rounding, grouping IDs) according to the spec. - Fiscal receipt template (XML) that renders the blackbox hash, VSC counter, POS system identifier, and event sequence number on every printed receipt. - X/Z daily report views with fiscal totals per VAT category. - Training-mode support: activates the FDM training flag so the device does not count test transactions. - Inspect popup (debug) for examining raw FDM messages. - Error/warning popup system with traceback messages from the device. - LocalStorage queue to replay pending mutations after a network outage. - pos_config / pos_session overrides: enforce blackbox constraints (only EUR, no rounding, mandatory restaurant mode, etc.), manage device pairing, and accumulate per-session fiscal counters. - Extensive unit-test suite: >6 000 lines covering the input generator's grouping-ID logic, price-consistency rules, and every mutation type against golden JSON fixtures. - Browser tour tests (oracle + regression tours). l10n_be_pos_blackbox_hr: - Clock-in / clock-out flows for employees trigger M140/M141 work in/out mutations; employee INSZ/NISS number is required and stored on hr.employee; pos_session accumulates per-employee work records. l10n_be_pos_blackbox_loyalty: - Gift-card and discount reward lines are mapped to the correct MPV fiscal codes (UC260/UC261); loyalty products are flagged so the input generator can calculate their contribution to the signed total correctly. l10n_be_pos_blackbox_self_order: - Intercepts self-order confirmation on kiosk screens to sign the order with the FDM before the confirmation page is shown; adds a controller to expose the required blackbox data to the kiosk frontend. l10n_be_pos_blackbox_settle_due: - Handles the "settle due" payment flow: products used to represent deferred payments are flagged and treated as zero-VAT lines in the signed message. l10n_be_pos_blackbox_urban_piper: - Patches the Urban Piper ticket-screen and pos_store so that online orders routed through Urban Piper are also signed before finalisation. community PR: https://github.com/odoo/odoo/pull/272155 task-id: 5864870
2 changes
Resolved issues and error corrections
Spanish companies can now open the Mod 349 tax return without the system crashing. The fix avoids a report check that assumed a different report layout, preventing an error when users access Tax Returns.
Original PR description
Steps to reproduce: - Install `Accounting` and `l10n_es` module - Switch to `Spain` company - Open `Tax Returns` Traceback: ```py File…
Steps to reproduce:
- Install `Accounting` and `l10n_es` module
- Switch to `Spain` company
- Open `Tax Returns`
Traceback:
```py
File "/data/build/enterprise/account_reports/models/account_return.py", line 2699, in _check_suite_common_ec_sales_list
engine_results = custom_handler._report_engine_ec_sales_report(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_sales_report.py", line 396, in _report_engine_ec_sales_report
return {next(iter(formulas_dict.values())): results}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
StopIteration
```
Cause:
In the method `_check_suite_common_ec_sales_list`, `formulas_dict` is built by taking `line_ids[0].expression_ids.grouped('formula')`. This assumes the first report line always has expressions defined, which holds true for standard EC Sales List reports.
However, Mod 349 has a different report structure where the first line is a "Summary" line with no expressions, resulting in `formulas_dict` being an empty dict. When `_report_engine_ec_sales_report` then calls
`next(iter(formulas_dict.values()))` to retrieve the formula key, it raises a `StopIteration` error, causing a crash whenever a Spanish company opens the tax return report.
Solution:
Override `_check_suite_common_ec_sales_list` for Mod 349 to only run the basic checks, bypassing the engine call that caused the crash. All other return types still go through the generic suite via `super()`.
opw-6222938
sentry-7513259974
Forward-Port-Of: odoo/enterprise#117850This change makes the French VAT submission use the correct form version based on the reporting period. It prevents reimbursement and VAT returns from being rejected by the tax authority when the campaign year changes.
Original PR description
The 3519 reimbursement form is rejected by the DGFiP with "Le millesime 25 du formulaire 3519 est inconnu dans la teleprocedure TVA". The 3310CA3 return is still accepted, because its layout is unchanged year-on-year, which hides the problem, but it is sent with a millesime that no longer matches the campaign. The millesime is the form-version year. The EDI-TVA 2026 campaign opened on 2026-02-09. last update: https://github.com/odoo/enterprise/pull/92542 opw-6275695 Forward-Port-Of: odoo/enterprise#120969 Forward-Port-Of: odoo/enterprise#120759
1 change
Enhancements to existing features
Backorder creation during receipt validation has been optimized so it can handle very large operations much faster. This reduces the risk of timeouts and database memory errors, helping busy warehouses complete receipts more reliably.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667