Most Odoo POS setup problems we get called in to fix are not software bugs. They are gaps left open during configuration: a cash drawer nobody is forced to count, a receipt template missing the tax ID, a stock location that lets the shop floor and the warehouse drift apart within a week. Odoo Point of Sale handles retail well. But it rewards a setup that matches how the shop actually works, not the default demo data.
This guide walks through the three areas that cause the most trouble in a retail go-live. Sessions and cash control. Receipt and tax invoice printing. Keeping shop-floor stock numbers you can trust.
Why Odoo POS setup deserves its own planning phase
A point of sale terminal is the one part of Odoo that non-accounting staff touch directly. Often under time pressure, with a customer standing at the counter. Mistakes here are visible immediately. They are also expensive to unwind after a few weeks of live transactions. We treat POS configuration as its own short phase, separate from the general Odoo implementation, with its own test session on real hardware before go-live.
Three things matter most from day one: the session and cash workflow, the receipt and tax document, and the link between the POS and the inventory app. Get those wrong and you inherit reconciliation work every single day.
Sessions and cash control that actually holds up
An Odoo POS session is the unit of accountability. One opening balance, a stream of orders, one closing count. The configuration choices that matter most:
- Opening and closing cash counts are mandatory, not optional. Odoo lets you skip the counted cash control screen. We always enable it. A cashier who counts the drawer at open and close catches shortages the same day, not a week later.
- One register equals one cash drawer equals one session. Do not let two people share a drawer across overlapping sessions. Need two checkout lanes? Configure two POS configurations against the same warehouse.
- Set a maximum cash difference threshold and a manager approval step for anything over it. Small differences are normal. Silent large ones are not.
- Close the session the same day it opens. A session left open overnight makes cash reconciliation messy and can hide exactly when an error happened.
- Decide who can reopen a closed session. We restrict this to a store manager or accounting role, never the cashier who closed it.
The trade-off: strict cash control adds a minute or two to opening and closing a till, and staff will push back on it. We tell retail clients this is non-negotiable in the first month. That is exactly when you discover whether staff are under-ringing or over-discounting.
Receipt and tax invoice printing, configured once and checked often
Odoo's POS receipt is a template. In most countries a plain receipt is not the same document as a tax invoice. Before go-live we confirm three things on the actual printer, not just in the browser preview:
- Company legal details are correct on the template. Name, tax ID, branch code if applicable, and address, pulled from the company record, not typed manually into the template.
- Tax breakdown prints per line and in total. For Thai VAT at 7 percent this means the receipt shows the VAT-inclusive total and the VAT amount separately. Most customers and auditors expect to see both.
- The fiscal position and tax mapping are set on the POS configuration, not left to default from the product. A product sold both in-store and to a VAT-exempt export customer needs the right tax applied automatically, not corrected by hand at the register.
For a full e-Tax Invoice in Thailand, the POS receipt is usually the starting point, not the finished document. We typically generate the formal e-Tax Invoice & e-Receipt from the Odoo ERP support side of Accounting, or through an integrated service provider, once the order posts. The regulatory format carries more fields than a printed slip needs for a walk-in customer. If your store serves business customers who ask for a tax invoice on the spot, plan this flow before go-live, not after the first complaint.
One real limitation worth naming: receipt printers vary a lot in paper width and command set. A template that looks fine at 80mm can clip totals at 58mm. We always test the final template on the exact printer model going into the shop, never a substitute.
Keeping shop-floor stock honest
This is where most retail Odoo setups lose credibility over time. A POS sale should decrement stock at the moment of sale. A few configuration choices decide whether that stock number stays trustworthy:
- Each physical store is its own warehouse or at minimum its own stock location, even under one company. Mixing two shops into one location makes it impossible to tell which store is actually short.
- Decide whether the POS updates stock in real time or at session close. Real-time updates are more accurate for fast-moving items but add load during a busy register. Close-time updates are simpler but mean the floor count and the system count disagree for the length of the open session. We default to real-time for stores with online stock visibility, such as click and collect or marketplace sync, and close-time for single-register shops with no online channel.
- Separate a damaged or return location from sellable stock. Refunds should not silently put a broken item back into available inventory.
- Run a physical count on a fixed schedule, not only when numbers look wrong. Weekly cycle counts on high-value or high-theft categories catch shrinkage before it compounds across a quarter.
- Reconcile POS stock moves against the inventory valuation report after each month-end close, the same way you reconcile cash. A retail business that integrates Shopee, Lazada or TikTok Shop alongside a physical counter needs this discipline even more. The same SKU is now moving through two sales channels against one stock number.
The honest trade-off here is effort versus accuracy. Real-time, location-separated, frequently-counted stock is more work than letting Odoo's defaults run quietly in the background. We think it is worth it the first time a stock discrepancy would otherwise take a day to trace instead of five minutes.
A short configuration checklist before go-live
| Area | Check before go-live |
|---|---|
| Sessions | Opening/closing cash count enforced, max cash difference set |
| Cash control | One drawer per session, manager approval for reopening |
| Receipts | Company tax ID and VAT breakdown print correctly on the real printer |
| Tax invoices | Fiscal position mapped, e-Tax Invoice flow confirmed with accounting |
| Stock | Warehouse per store, damaged-stock location separated from sellable stock |
| Reporting | Month-end reconciliation of POS cash and stock moves scheduled |
Where this fits with the rest of your Odoo setup
POS does not run on its own. It depends on correct tax configuration in Accounting, warehouse structure in Inventory, and often a connector if you also sell through a marketplace. We approach retail and e-commerce Odoo setup as one connected scope rather than configuring the register in isolation. Our retail and e-commerce ERP work covers the POS, the backend inventory, and the channel integrations together, so the stock number on the shop floor matches the one in the system of record. For stores already selling on marketplaces, our API integration services and the Shopify Odoo Connector keep that same SKU in sync across channels.
If you are planning a POS rollout across more than one store, start with the warehouse and tax structure before you touch the register screen. The register is the easy part. The stock and cash discipline behind it is what determines whether your numbers are still trustworthy three months after go-live.



