Point of sale in Odoo and ZATCA e-invoicing: getting the simplified invoice right from the till
How Odoo point of sale works, how the simplified invoice gets its QR code and ZATCA compliance, what happens when the internet drops, and what makes the link fail.
A shop with a till and e-invoicing has two problems instead of one: the till must be fast and simple for staff, and the invoice it prints must meet the requirements of the Zakat, Tax and Customs Authority. Many solutions fix one and break the other.
Odoo has a point-of-sale module that runs in the browser, connected to inventory and accounting, and it can be linked to e-invoicing. This post covers how it works, what correct setup needs, and what makes the link fail. For the background on e-invoicing itself, read ZATCA e-invoicing on Odoo first.
How Odoo point of sale works
The till is a screen in the browser: the cashier opens a session at the start of the shift (recording the opening cash float), sells by scanning barcodes or picking products, takes payment (cash, card, or split), and prints the invoice. At the end of the shift they close the session and record the actual cash, and the system shows any difference.
Behind the screen: every sale reduces stock in the shop's location instantly, and posts to accounting when the session closes (or instantly, depending on setup). The cashier knows nothing about this, which is the point.
What sets it apart from a standalone till
- One balance: the online store, the till and the warehouse all see the same number. We covered this in inventory management in Odoo.
- Runs on any device: a laptop, a tablet or an ordinary POS terminal, as long as it has a modern browser. The thermal printer, scanner and cash drawer connect.
- Several branches, several tills, all in one system with unified reports.
- Promotions, discounts and loyalty from the same system, without external tools.
E-invoicing from the till: the simplified invoice
Till sales to consumers produce a simplified invoice. The core requirements of the second phase (integration):
- The invoice is generated in an approved electronic format with the required fields (business name, VAT number, date and time, line items, tax, total).
- A QR code on the printed invoice that the authority's app reads and matches against the data.
- Reporting: simplified invoices are sent to the authority within 24 hours of issue (unlike tax invoices for businesses, which need clearance before issue). This difference matters for the till: selling does not stop to wait for the authority's response.
- A digital certificate per invoicing unit, linked to the business's account with the authority. In Odoo the certificate belongs to a sales journal, and each till issues its invoices on the journal assigned to it.
- Sequential numbering and a hash link to the previous invoice, with no gaps.
In Odoo this is done through the Saudi e-invoicing module that connects invoices issued from point of sale to the authority's platform, handling the certificate, signing and sending in the background.
What happens when the internet drops
Every shop's question. Odoo point of sale can keep selling without a connection for a while: invoices are stored locally and sent to the server when the connection returns. Reporting to the authority has a 24 hour window from issue, so an outage of an hour or two does not breach the rules provided sending happens before the window closes. What breaches them is a branch that loses its connection overnight and nobody notices until the next afternoon, and that needs monitoring and alerts in the system: unsent invoices equal an alert to the person responsible.
Correct setup from the start
- Company, VAT number and address exactly as registered with the authority. One character's difference rejects the invoice.
- Taxes on products: each product has the correct tax setting (standard, zero-rated, exempt). Mistakes here produce wrong invoices that only surface later.
- The test environment first: the authority provides a simulation environment, and invoices are tested end to end there before production.
- The till's journal onboarded with its certificate and documented, with a plan for when it expires, the device changes or a new branch opens.
- A printer that renders the QR code clearly enough for a phone to read.
- Returns and exchanges: a credit note linked to the original invoice, not a deletion. Point of sale must support this from the screen.
- Cashier training on only three cases: a normal sale, a return, and closing the session.
The end of day routine: five minutes that save a month
Most till problems do not show up on the day they happen. They show up at month end when the accountant tries to reconcile. The fix is not a more complicated system, it is a short routine the branch manager runs every night:
- Close every session. A session left open from yesterday mixes two days of sales in one report and delays posting to accounting.
- Count the cash and compare it with the system. Record a small difference with its reason (change, a cash refund nobody logged). A difference that repeats every day on the same cashier is the one worth asking about.
- Reconcile card payments. The card total in the session should equal the settlement report printed by the card terminal itself. When it does not, a cashier usually picked "cash" for a card payment or the other way round.
- Invoices not yet sent to ZATCA. One list to open, and it should be empty, or everything on it should be going out well before the 24 hours run out.
- Rejected invoices. A rejection comes with a message that says why, and the cause is usually setup: missing customer details, the wrong tax on a product. Fix the setting itself so it does not happen again tomorrow. An accepted invoice is never edited or deleted: the correction is a credit note and a new invoice, as explained in ZATCA e-invoicing on Odoo.
A shop that does this every night never needs a painful month end, because each day is already closed on its own.
Moving from your current till to Odoo without shutting the shop
Owners dread the switchover, and they are right to. A day of wrong prices or a till that freezes at the busiest hour costs more than any licence. What turns it into an ordinary day is the order of work:
- Clean the product list first. Every product with its correct barcode, price and tax. This is the longest step and the most important, because a new till repeats every mistake in the old list, only faster.
- Onboard with ZATCA before switch day. A full run in the simulation environment, then production, so the first real invoice is not the test.
- Count opening stock the night before. Odoo should start with what is actually on the shelf, not with what the old system believes.
- Pick a quiet day. Your slowest day of the week, not the start of the weekend.
- One system issues invoices per branch. From the moment you switch, the old till stops issuing. Two systems invoicing for the same branch break the reports and make any audit harder. Export and keep the old till's reports and invoice archive; you will need them.
- Someone who knows the system is in the shop for the first week. Physically there, not on the phone. The first return and the first session close are what actually train the cashier.
What fails at this stage is rarely technical. It is the same patterns we described in why Odoo implementations go wrong: data nobody cleaned and training squeezed into the last day.
Why the link fails
- Business details do not match the authority's record.
- Taxes set at invoice level rather than product level, producing wrong amounts.
- The certificate expired, or the till issues on a journal that was never onboarded.
- A return done by deleting the invoice instead of a credit note, breaking the sequence.
- An old version of the module behind the authority's updates.
- Pending invoices that were never sent, with nobody noticing.
Do you need Enterprise?
The point-of-sale module exists in the Community edition, and Saudi e-invoicing is available as community and official modules depending on the version. We explained where the ZATCA connection sits between the editions in ZATCA e-invoicing on Odoo. For your shop the answer depends on your version and requirements, and we work it out with you rather than generalising.
Questions shop owners ask us
We have an old till with its own software. Can we use it with Odoo?
If the device is just a computer with a browser, a printer and a scanner, yes. If it is locked to one program and runs nothing else, you need an ordinary device, which is often cheaper than the one you have.
How many tills can run on the same system?
For small and medium shops there is no practical limit. Each till is its own session, each branch has its own stock, and the reports come together.
Can the till issue tax invoices for businesses too?
Yes, but the path is different: it needs the customer's VAT details and clearance by the authority before issue, not reporting after. We set the till up to tell the two cases apart on its own.
Does the card terminal have to be connected to Odoo?
No. The simplest setup is that the cashier picks "card" in Odoo, types the amount into the terminal, and the two are reconciled at the end of the day. A direct integration saves the typing and prevents a wrong amount, but whether it exists depends on the terminal provider and your Odoo version, so check it before you buy the terminal, not after. Taking payment online is a separate question, covered in payment gateways in Saudi.
What happens when the authority updates its requirements?
The module gets updated, and that is part of the support agreement. A connection that nobody looks after is the one that stops at the first update.
The short version
Point of sale in Odoo gives staff a simple till connected to inventory and accounting, and it can issue a ZATCA-compliant simplified invoice with a QR code and background reporting. What separates a working link from a failing one is setup: matching details, taxes on products, an onboarded journal for every till, returns by credit note, and monitoring of pending invoices.
See Odoo implementation with ZATCA for what we do, or book a free consultation and we will look at your current till and tell you what it needs.