Daily updates from Odoo
Wednesday, June 10, 2026
4 changes · 17.0
New functionality added to Odoo
This update introduces new invoice types specifically designed for Jordan's export regulations, including 'transit,' 'foreign trade,' and 'free zone transfer.' It ensures these types are only accessible to registered Jordanian taxpayers, aligning with local tax laws and improving compliance. This change supports smoother international trade operations.
Original PR description
Extend l10n_jo_edi_invoice_type with JoFotara scope codes (3-5): transit (3), foreign trade (4), and free zone transfer (5). Validate that scope codes 3-5 are only available to registered taxpayers. task-4769255 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves a technical issue where VoIP registration could fail due to idle sessions, causing error dialogs and preventing users from making calls. The fix ensures that the registration process is reliably restarted when a connection is lost, preventing the system from getting stuck and improving the user experience.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.This update resolves an issue where a JSON decoding error could occur when downloading ETA invoice PDFs. A recent change introduced a workaround, but a new error type wasn't being caught. This fix adds a catch block to properly handle the `json.JSONDecodeError`, ensuring stable invoice processing.
Original PR description
When we download the ETA invoice PDF, a JSONDecoderError can happen when calling the json() method on the request. This error is properly caught by Odoo : https://github.com/odoo/odoo/blob/7a9a340e0dbac470c4bea3f8ce8a32e55f3e82e6/addons/l10n_eg_edi_eta/models/account_edi_format.py#L58-L60 However, the following commit introduced a monkeypatch to handle errors when the simplejson library is installed : 2435fe76eec1fc4320ef71726fc7f16ece653a32 If we meet the conditions, the original error is replaced by a json.JSONDecodeError which is not caught during the previous process. We propose to add this error to the catch block. This modification was inspired by the commit d483dac144a9caf84c44b9d8d394ea327ca87cfe. opw-6266862 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where order totals and refund amounts were incorrectly calculated after tax changes or refunds were processed in Point of Sale. The fix ensures historical order prices are preserved, providing accurate totals for both paid orders and refunds. This improves the reliability of financial reporting within the POS system.
Original PR description
Steps to reproduce 1. Create a product at $30 with a 15% tax-excluded tax (total = $34.50) 2. Sell and pay the order 3. Edit the tax and toggle price_include = True 4. Open POS, go to Orders > Paid —…
Steps to reproduce 1. Create a product at $30 with a 15% tax-excluded tax (total = $34.50) 2. Sell and pay the order 3. Edit the tax and toggle price_include = True 4. Open POS, go to Orders > Paid — the order total shows $30 instead of $34.50 5. Click Refund — the refund total also shows $30 instead of $34.50 Issue https://github.com/odoo/odoo/blob/130c5266e0fc37f64f58f67b44c84130643bec20/addons/point_of_sale/static/src/app/store/models.js#L1067-L1090 get_all_prices() recomputes prices from price_unit using current tax objects, ignoring price_subtotal/price_subtotal_incl already serialised in the order JSON. When price_include changes on a tax after an order is paid, the historical total is lost. https://github.com/odoo/odoo/blob/130c5266e0fc37f64f58f67b44c84130643bec20/addons/point_of_sale/static/src/app/store/models.js#L1580-L1608 this.locked was assigned after the orderlines loop, so Orderline.init_from_JSON could not use it to distinguish paid from draft orders. https://github.com/odoo/odoo/blob/130c5266e0fc37f64f58f67b44c84130643bec20/addons/point_of_sale/static/src/app/screens/ticket_screen/ticket_screen.js#L653-L668 _prepareRefundOrderlineOptions passed price_type: "automatic" which triggered a fresh get_all_prices() with current taxes, producing the same wrong total on refunds. Solution Move this.locked assignment before the orderlines loop. When locked, pin price_subtotal/price_subtotal_incl from JSON in Orderline.init_from_JSON and return them early in get_all_prices(), scaling by qty/lineQty so per-unit display calls (get_all_prices(1)) remain correct. Read amount_total/amount_tax from JSON and return them directly in get_total_with_tax()/get_total_tax() for locked orders. Carry price_subtotal/price_subtotal_incl in the refund detail snapshot and inject them (scaled by partial-refund ratio) as extras on the refund orderline. opw-6097256