Odoo 19 → 20

Odoo 19 to 20 Point of Sale migration: a guide for custom modules

A wide-reaching POS release where several server-side data-loading, loyalty and hardware-config entry points were removed or reshaped, so custom modules that hooked into ordering, coupons or terminal setup will need targeted rework rather than a blanket pass.

1,817 verified changesPoint of Saleverified on Odoo 20
1,817
verified changes
117
models affected
47
modules affected

Change breakdown

Changed method356
Added method300
Changed view / record234
Removed JavaScript method184
Removed method171
Added field145
Removed JavaScript module76
Removed field67

Removed and renamed items are what a custom module feels first — they break references at load time. Added and internally-changed items rarely touch existing code.

Where the changes land

point_of_sale1,032
pos_restaurant209
pos_self_order162
pos_hr52
pos_loyalty50
pos_online_payment36
pos_sale36
pos_event24

Changes reach 47 modules in all — but they cluster. point_of_sale carries the most (1,032 changes), so it's the first place to look if you extend it.

A wide-reaching POS release where several server-side data-loading, loyalty and hardware-config entry points were removed or reshaped, so custom modules that hooked into ordering, coupons or terminal setup will need targeted rework rather than a blanket pass.

Odoo 20 was released on 24 September 2026. This guide covers Odoo 19 → 20 Point of Sale, Community Edition, built from the released version; Enterprise modules are not included in these counts. It counts 1,817 verified changes across 47 core modules.

Two things the sections below do not dwell on. First, 286 of the changes in this release are JavaScript, including 184 removed front-end methods and 76 removed modules, so budget for the POS front end as much as for the server side. Second, several terminal modules are removed in Odoo 20 (pos_restaurant_adyen, pos_restaurant_stripe, pos_self_order_adyen, pos_self_order_stripe, pos_self_order_viva_com) while new ones arrive (pos_bancontact_pay, pos_stock, pos_sale_stock, pos_sale_delivery, pos_partner_autocomplete); a manifest that depends on a removed one fails at install.

Start by treating this as a data-flow and integration review rather than a field-by-field chase. The safest first step is to grep your module for the specific POS server methods and fields you call from JavaScript, controllers or overrides — that's where the breakage concentrates — and confirm each still exists before you touch anything else. Loyalty and gift-card handling, self-order/kiosk data loading, and printer/terminal configuration are the three areas most likely to bite, because entry points there were removed outright rather than renamed.

Expect to revisit the loyalty and payment-method sections in particular, since those tend to keep moving late.

What needs the closest look

Kiosk self-ordering data endpoint is gone

Removed method — PosSelfKiosk.get_self_ordering_relations

This public route was how the self-order kiosk fetched its full set of loading parameters for a given config. If your module extended kiosk data loading or called this relations endpoint from a custom frontend, that path no longer exists — move your logic into the current self-order data-loading flow instead of relying on this route.

Removed in Odoo 20 — it was defined as:

@http.route("/pos-self/relations/<config_id>", type='jsonrpc', auth='public')
def get_self_ordering_relations(self, config_id=None, access_token=None, table_identifier=None):

Gift-card validity check no longer server-side here

Removed method — loyalty.card.get_gift_card_status

The helper that validated a gift code (checking expiry, remaining points, program type and usage history) and returned its status has been removed from loyalty.card. Any custom kiosk or POS screen that pinged this to verify a card before applying it must be reworked to use the current gift-card handling rather than this specific call.

Removed in Odoo 20 — it was defined as:

@api.model
def get_gift_card_status(self, gift_code, config_id):

Loyalty-partner lookup by code removed

Removed method — loyalty.card.get_loyalty_card_partner_by_code

The convenience method that resolved a loyalty program's partner from a scanned or typed code is gone. If you looked up cardholders this way when scanning loyalty codes, replace it with your own search on loyalty.card or the current loyalty resolution logic.

Removed in Odoo 20 — it was defined as:

@api.model
def get_loyalty_card_partner_by_code(self, code):

Custom create for Coins/Bills no longer parses the name

Removed method — pos.bill.name_create

pos.bill used to override name_create so that typing a number both named the denomination and set its value, raising an error on non-numbers. That override is removed, so if your module created bill denominations by name, you'll now need to pass the numeric value explicitly rather than relying on the name being parsed.

Removed in Odoo 20 — it was defined as:

@api.model
def name_create(self, name):

Manager-access employee list dropped from POS config

Removed field — pos.config.advanced_employee_ids

The field that auto-collected employees tied to POS Manager users has been removed from pos.config. If your access or restriction logic read this list to decide who has elevated rights, you'll need to derive manager access from the underlying user roles yourself.

Present in Odoo 19, removed in 20:

advanced_employee_ids = fields.Many2many(
        'hr.employee', 'pos_hr_advanced_employee_hr_employee', string="Employees with manager access",
        help='Employees linked to users with the PoS Manager role are automatically added to this list')

Auto-validation toggle for terminal payments removed

Removed field — pos.config.auto_validate_terminal_payment

The config flag that automatically validated orders paid via a payment terminal is gone. If your module read or set this to control terminal payment flow, revisit how you finalise terminal-paid orders under the new behaviour.

Present in Odoo 19, removed in 20:

auto_validate_terminal_payment = fields.Boolean(default=True, help="Automatically validates orders paid with a payment terminal.")

Loyalty history is no longer written through this order hook

Removed method — pos.order.add_loyalty_history_lines

The method on pos.order that built loyalty history lines from coupon data (mapping temporary IDs to real card IDs and recording points won and spent) has been removed. If you extended coupon/loyalty accounting during order sync, that customisation must be reattached to the current loyalty history mechanism.

Removed in Odoo 20 — it was defined as:

def add_loyalty_history_lines(self, coupon_data, coupon_updates):

Also worth checking

Loyalty and coupons. Beyond the removed helpers above, several loyalty touchpoints shifted. On pos.order.line the coupon link was renamed to card_id, so any override that reads a line's coupon reference needs repointing, and the reward_identifier_code field on that model is gone. The source_pos_order_partner_id field on loyalty.card has also been dropped, and the order-side confirm_coupon_programs method no longer exists — if your module confirmed or reconciled programs at order close, move that into the current flow. Note too that pos.order.line no longer carries its own unlink override, so if you relied on side effects there, check them.

Invoicing. The order's is_invoiced flag was renamed to is_singly_invoiced. Anywhere your reports, filters or accounting hooks test whether an order is invoiced, update the field name and re-read what it now means.

Printers and hardware config. Printer setup was tidied: the Epson printer IP field on pos.config and the company link on pos.printer were removed. If your module configured receipt/kitchen printers or scoped them per company, adjust to the new printer configuration model. The kitchen preparation change helper get_preparation_change on pos.order is also gone, so custom preparation-display logic needs revisiting.

Payment methods. A few payment-method entry points disappeared: the Viva.com status poll, the QR-code generator, and the hide_use_payment_terminal field. If you integrated a terminal or QR payment provider through these, rebuild against the current payment-method API.

Product loading and staff. The get_limited_product_count helper on pos.config was removed, so custom limited-product loading should use the current data-loading path; and the basic_employee_ids list on pos.config is gone alongside the manager list, so employee-scoping logic needs reworking.

Beyond these, 939 smaller internal changes exist — only relevant if you override Odoo's private helpers or compute methods.

Your migration checklist

  1. Search your module for the removed server methods (self-order relations, gift-card status, loyalty-partner lookup, coupon confirmation, preparation change, payment status/QR helpers) and rebuild each against the current flow.
  2. Update every reference to renamed fields: is_invoiced to is_singly_invoiced, and the order line's coupon_id to card_id.
  3. Rework any code that read the removed pos.config fields — the employee access lists, the auto-validate terminal flag, the Epson printer IP and limited-product count — using the new configuration and data-loading paths.
  4. Revisit printer and payment-method integrations, accounting for the dropped company link on pos.printer and the removed payment-method fields and helpers.
  5. Retest the full loyalty and gift-card lifecycle in POS, since history writing, program confirmation and card lookups all moved.
  6. Run your full test suite on Odoo 20 and exercise every affected workflow end to end before go-live.

Related guides

Is your module ready for Odoo 20?
Scan it free — every breaking change above, found in your actual code, with AI fixes verified on a real Odoo server.
Scan your module →