Pricelists and Promotions in Odoo 20

Pricing is where an ERP either earns its keep or creates quiet chaos. In Odoo, two engines handle it: pricelists, which set the price a customer segment pays in the first place, and discount and loyalty programs — promotions, coupons, and points — which reward behaviour on top of that price. Odoo 20, released in September 2026, does not replace either engine. It sharpens both: pricelist rules can now follow the calendar, discount codes can be locked to one use per customer, loyalty points can expire, and the shop lets visitors switch pricelists on every page. Here is how they fit together, and what is new in 20.

Two engines, two different jobs

The Odoo 20.0 documentation draws the line clearly: discount and loyalty programs offer “more varied, public, and time-sensitive pricing options than pricelists.”

  • Pricelists are structural. A pricelist is a list of prices or price rules that overrides the sales price on the product form, tailored to all products or to specific customers, groups, orders, or time periods. Think wholesale versus retail, CAD versus USD, contract pricing. Pricelists suggest a price; a salesperson can still override it on the order.
  • Promotions are behavioural. A promotion reacts to what is in the cart — order total, quantities, products, a code typed at checkout — and grants a reward: a discount, a free product, or free shipping. Loyalty programs let customers accumulate points across orders and exchange them later.

How pricelists work — the long-standing engine

Pricelists are enabled in the Sales settings, under Pricing. Each has a name, a currency, an optional company, and optional country groups. If none is assigned to a quotation, Odoo applies the Default pricelist — the first in the list without an assigned country group. Customers carry a pricelist on their contact form (Sales & Purchase tab), copied automatically onto their quotations, where it can still be changed manually.

Three price types

Every price rule in Odoo 20 uses one of three computation types:

  • Discount — a percentage off a base price (the product’s sales price or another pricelist). A negative percentage becomes a markup. This discount is visible to the customer on the quotation.
  • Formula — the flexible option, based on the sales price, the cost, or another pricelist, then applying a discount or markup, an optional rounding step (Round off to), and an Extra Fee added afterwards. Round to a multiple of 10 with an extra fee of -0.01 and prices end in 9.99. Unlike Discount, a formula’s reduction is not shown to the customer; they simply see the resulting price.
  • Fixed Price — a flat per-unit price overriding the product’s sales price entirely.

Rule conditions and priority

Each rule targets a product or a category (leave the target blank to cover everything), and can carry a minimum quantity, a packaging, and a validity period. When several rules could apply, Odoo resolves them in a documented order:

  1. Most specific wins — variant beats product, product beats subcategory, subcategory beats parent category, which beats all-products.
  2. Largest minimum quantity wins — a bulk rule for 10+ units is not overridden by a generic rule that also matches.
  3. Category order — the configured category hierarchy breaks remaining ties.
  4. Newest rule wins — if all else is equal, the most recently created rule applies, letting you supersede an old rule without deleting it.

What is new for pricelists in Odoo 20

The release notes list a focused set of Sales changes. Four matter directly for pricelists; two more change how prices appear in the shop.

Periodic pricing: rules by period and day of week

The headline addition is periodic pricing: you can now “define pricelist rules (including surcharges) for specific periods or days of the week.” Long-standing validity dates could already switch a rule on and off between two dates; periodic pricing adds rhythm. A weekend surcharge or weekday-only trade pricing no longer needs a staff member editing validity dates every week — the rule itself knows which days it applies to. Odoo 20 also adds price rules per packaging type, so singles, six-packs, and cases of the same product can each carry their own rule instead of duplicated products.

Fixed Price rules now respect attribute extras

A subtle fix with real money attached: “Extra prices from attribute values are now applied on top of ‘Fixed Price’ pricelist rules.” Previously, a fixed price could silently swallow the extra charge for a premium variant attribute. In 20, the fixed price sets the base and the attribute extra is added on top, which is what most price books intend.

In the shop: selector everywhere, tax display per pricelist

Two eCommerce changes complete the picture. The pricelist selector is now available on all pages of an eCommerce website, not just tucked into the shop flow. And you can now “set whether the displayed prices include or exclude taxes at pricelist level,” so one website serves B2C shoppers tax-included prices and B2B accounts tax-excluded prices at the same time. Pricelist reports also improve: grouped by product category, with Product Reference and Barcode included, and filterable by a specific date — so you can reproduce the pricelist as it stood on a given day.

Promotions, coupons, and loyalty — the second engine

Discount and loyalty programs are switched on in Sales settings via the Promotions, Loyalty & Gift Card setting, and work across Sales, Subscriptions, eCommerce, and Point of Sale. A new database gets seven starter templates — a promotional program (10% off orders over $50), a promo code, Buy X Get Y (buy 2, get the 3rd free), a next-order coupon, a loyalty card, a coupon program, and a fidelity card (buy 10, get a discount on the 11th).

Program types

  • Coupons — generated single-use codes granting a reward immediately.
  • Loyalty Cards — points earned per order, per currency spent, or per unit, exchanged for rewards on current or future orders.
  • Promotions — conditional rules on the order itself; when conditions are met, the reward applies automatically.
  • Discount Code — a code entered at checkout to unlock a discount.
  • Buy X Get Y — credits accumulate for every X items bought, traded in for Y items.
  • Next Order Coupons — a completed order generates a single-use coupon for the next one.

Rules and rewards

Every program is built from conditional rules and rewards. Rules can require a minimum quantity (at least 1, so a reward never fires on an empty action), a minimum purchase amount — tax included or excluded — and can be scoped to specific products, categories, or tags. Rewards are a free product, a discount (percentage, fixed amount, or amount per point; applied to the whole order, the cheapest product, or specific products, with an optional maximum), or free shipping. Programs can be limited by dates, capped by number of uses, and restricted to particular pricelists, websites, points of sale, or companies — linking a program to a pricelist is how different segments share one loyalty scheme on top of different base prices.

What is new for promotions in Odoo 20

  • Single-use discount codes. The Sales release notes add: “Allow discount codes to be used only once per customer.” Shared codes leaking onto coupon sites is the oldest problem in eCommerce promotions; a per-customer limit keeps a welcome code a welcome code.
  • Loyalty point expiration. Odoo 20 lets you “set an expiration date for loyalty points.” Expiring points create a reason to return before the date, and stop an ever-growing points liability on your books. Per the 20.0 documentation, the soonest-to-expire points are spent first, expired points no longer count toward a card’s balance, and customers see expiration dates in their portal.
  • Loyalty progress in the cart. Progress bars now appear in cart notifications and the cart summary, showing progress toward unlocking a reward. A promotion the customer cannot see does not change behaviour; the progress bar closes that gap.
  • Loyalty for subscriptions, and one pricing engine. The Subscriptions section of the release notes adds: “Create loyalty rules and rewards for subscriptions.” And Sales, Subscription, and Rental prices have been unified in a single “Prices” tab using the standard pricelist engine; when a pricelist discount applies to a rental product, the shop now shows the original price crossed out beside the discounted one. One engine, one set of rules to audit.

A practical configuration order

  1. Build pricelists first — one per currency and segment you serve, with an all-products rule as a safety net so nothing falls through unpriced.
  2. Test the priority ladder with a product matching three rules — category, product, variant — and confirm the intended price is the price shown.
  3. Add promotions second, scoped deliberately: dates set, usage limited where a code could leak, minimum quantity 1.
  4. Decide visibility. Use Discount when the customer should see the reduction; use Formula when the final price should simply be the price.
  5. Re-run the pricelist report filtered to a past date after any change, so the quoted price book matches the rules the system applies.

Odoo 20 does not reinvent pricing. It removes the recurring annoyances — rules that could not follow a weekly rhythm, fixed prices that ate attribute extras, codes that could be reused forever, points that never expired — and leaves two engines that each do one job well: structural pricing in pricelists, behavioural pricing in promotions.

Further reading

Leave a Comment