Friday, September 25, 2026
5 changes · 18.0
Enhancements to existing features
Xendit payments are updated to use Xendit's newer hosted payment flow because older payment endpoints are being retired. Customers will now be redirected to Xendit's payment page for all payment methods, while existing saved card tokens remain supported and administrators are warned to update webhook settings.
Original PR description
Xendit is deprecating the v2/invoices and credit_card_charges endpoints for new payments. This switches checkout and card sessions to the Payment Sessions API (/sessions) and charges v3 tokens…
Xendit is deprecating the v2/invoices and credit_card_charges endpoints for
new payments. This switches checkout and card sessions to the Payment
Sessions API (/sessions) and charges v3 tokens through /v3/payment_requests,
while still charging pre-existing v2 tokens through the legacy
credit_card_charges endpoint, as there is no migration path for them.
- the inline card form, its direct flow, and the Xendit SDK are removed; all
payment methods now redirect to the Xendit-hosted payment link
- a v3 token charge that unexpectedly still requires 3DS exposes the
authentication URL as a processing value; the frontend navigates the top
window to it directly, since Xendit's challenge page must be top-level and
only accepts GET
- a customer returning from checkout, or from a 3DS challenge, is checked
directly against Xendit before falling back to pending, in case the
webhook is delayed or dropped
- webhook payloads are unwrapped from their {event, data} envelope, and
transactions are looked up by reference_id, falling back to external_id
for legacy charges and to a suffix-stripped reference_id otherwise
Upgrade / stable-version compatibility:
- the inline_form view is emptied rather than removed (it's noupdate, and
ondelete='restrict' would abort the module update otherwise); it is never
rendered
- xendit_public_key is kept but unused, and several touched methods keep
their old name or signature (_xendit_make_request, _xendit_create_charge,
_xendit_prepare_invoice_request_payload, _get_redirect_form_view, the
/payment/xendit/payment route), since partners may override them and a
stable version can't drop or break an override
- bump the module version so partners upgrading notice the change
Webhook migration notice:
Xendit replaced the single webhook field with separate v3 event groups, so
already-configured databases silently stop receiving updates. Remind admins
once via the daily autovacuum cron (works without an upgrade or a new
ir.cron record), tracked through the payment_xendit.v3_notification_sent
system parameter so it's only sent once.
Task-6373405The update prevents non-French companies from being checked against the French business directory when validating electronic invoicing endpoints, even if they have French-style identifiers recorded. This reduces incorrect validation attempts and helps international partner setup work more smoothly.
Original PR description
for non-french partners, a check on the annuaire shouldnt happen when checking their endpoints, even if they have a siren/siret related-task-id-6327357
Resolved issues and error corrections
This fix prevents invoice tax total calculations from failing when the Sales app is not installed. It only applies down payment-related context when that information is available, improving reliability for companies using electronic invoicing without Sales.
Original PR description
In https://github.com/odoo/odoo/pull/283009 we make a change passing in is_downpayment as context on an account_move_line, based off a field value on an account_move_line. This field is only brought in by the sales module, and will throw an error if we do not have sales installed. This fix extends the function, `_get_invoice_line_tax_totals_vals_list`, that needs this context to simply pass in the context when available. https://github.com/odoo/odoo/pull/283009 was only merged into 17 and 18, only r+ this to 18.0. runbot-[947355](https://runbot.odoo.com/odoo/error/947355) Forward-Port-Of: odoo/odoo#290557
Documentation and clarification updates
This pull request records the contributor license agreement signature for a new contributor. It helps ensure their related contribution can be accepted under Odoo's legal contribution requirements.
Original PR description
Signature of the Odoo Individual Contributor License Agreement v1.0 for @mmircoli-nexapp, needed for the fix related to #290493. I confirm I have read the [CLA](https://github.com/odoo/odoo/blob/18.0/doc/cla/icla-1.0.md) and that the committer email matches the one used in my contributions.
Fixed an issue where confirming or processing rental orders could fail when one product variant had a kit setup but another variant did not. This keeps rental workflows moving correctly for businesses using variant-specific kits.
Original PR description
Steps to reproduce: ------------------- - Install `sale_mrp_renting` module. - Enable **Rental Transfers** from setting - Create a storable rental product with two variants: - Green - color - Grey -…
Steps to reproduce:
-------------------
- Install `sale_mrp_renting` module.
- Enable **Rental Transfers** from setting
- Create a storable rental product with two variants:
- Green - color
- Grey - color
- Create a Kit BoM for the Green variant only and add a component
- Create a rental order for one Grey unit
- Confirm the rental order
Issue:
------
Confirming the rental order raises a `ZeroDivisionError`
```txt
File "/data/build/enterprise/sale_mrp_renting/models/sale_order_line.py", line 21, in _get_qty_procurement
qty_to_compute = outgoing_moves._compute_kit_quantities(self.product_id, order_qty, bom, filters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/addons/mrp/models/stock_move.py", line 785, in _compute_kit_quantities
kit_qty = kit_qty / kit_bom.product_qty
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
ZeroDivisionError: float division by zero
```
Cause:
-------
When the user confirms the order, `action_confirm()` calls `_action_confirm()`, which launches stock rules through `_action_launch_stock_rule()`. This calls `_get_qty_procurement()` to determine the quantity already procured.
The rental override then checks whether the product has a Kit BoM using:
```python
'phantom' in self.product_id.bom_ids.mapped('type')
```
https://github.com/odoo/enterprise/blob/1913d8b8c411086914278600f80ef8dd45e1fc3b/sale_mrp_renting/models/sale_order_line.py#L10-L23
However, `bom_ids` is defined on `product.template` through `product_tmpl_id`.
Therefore, Grey also sees the Kit BoM belonging to Green, since both variants share the same template.
See the [BoM field definition](https://github.com/odoo/odoo/blob/c270965ec11c95e5e2866b30f8fa2c90287c6e8a/addons/mrp/models/product.py#L21-L25).
The condition evaluates to `True`, and the code enters the kit calculation. It then calls:
```python
bom = self.env['mrp.bom']._bom_find(self.product_id, bom_type='phantom')[self.product_id]
```
Unlike the template-level check, `_bom_find()` looks for a BoM applicable to the actual variant.
Since the only Kit BoM is restricted to Green, the lookup correctly returns an empty recordset for Grey.
See the [BoM lookup](https://github.com/odoo/odoo/blob/c270965ec11c95e5e2866b30f8fa2c90287c6e8a/addons/mrp/models/mrp_bom.py#L351-L388).
For an order of one Grey unit, the values are:
```text
product.bom_ids.mapped('type') = ['phantom']
bom = mrp.bom()
order_qty = 1.0
bom.product_qty = 0.0
```
The quantity conversion leaves `order_qty` unchanged because the empty BoM has no destination UoM.
See the [UoM conversion](https://github.com/odoo/odoo/blob/c270965ec11c95e5e2866b30f8fa2c90287c6e8a/addons/uom/models/uom_uom.py#L211-L220)
The code then passes this empty BoM to `_compute_kit_quantities()`. Its first division becomes `1.0 / 0.0`, raising `ZeroDivisionError`. The zero comes from the empty recordset, not from Green's BoM quantity.
[See failing division](https://github.com/odoo/odoo/blob/c270965ec11c95e5e2866b30f8fa2c90287c6e8a/addons/mrp/models/stock_move.py#L774-L786)
Fixing confirmation alone leaves the same issue in later operations. Delivered-quantity computation also passes an empty BoM to the kit helper when completed outgoing moves exist.
https://github.com/odoo/enterprise/blob/1913d8b8c411086914278600f80ef8dd45e1fc3b/sale_mrp_renting/models/sale_order_line.py#L25-L49
After confirmation and pickup succeed, validating the return triggers `stock.move._action_done()`. Its kit check also accepts Grey based on Green's BoM, then passes an empty BoM to `_compute_kit_quantities()`, causing the same division-by-zero error.
https://github.com/odoo/enterprise/blob/1913d8b8c411086914278600f80ef8dd45e1fc3b/sale_mrp_renting/models/stock_move.py#L10-L30
Fix
---
Only perform kit calculations when `_bom_find()` returns a matching BoM.
- For procurement, return the quantity computed by the parent method when no matching BoM exists.
- For delivered quantities, delegate lines without a matching kit BoM to the parent computation through `todo_ids`.
- For returns, skip kit-specific calculations when no matching BoM exists, preserving the normal rental return handling.
---------
opw-6588790