Point of Sale

Retail and restaurants

MarketplaceOperationsVersion 0.1.0manifest

What it is for ​

Model a shop till: configuration, cash-controlled sessions, orders with lines and payment lines per method. It records what happened at the till; it is not a payment terminal integration, and card numbers must never be stored.

What the package does and does not do ​

Shop tills: a point-of-sale configuration, cash-controlled sessions that are opened and closed, orders with lines, and payment lines per method. A refund and the closing of a session need a human approval from a manager; agents may only propose them. Totals, change and cash differences are entered, not computed. Card numbers must never be stored; keep only the payment provider's reference. Needs the Products package.

Models ​

pos_config ​

A point of sale (a till or a shop) and its rules

Read group: pos.user. Write group: pos.manager.

FieldKindData classPersonal dataGroupAgents seeDescription
nametextnonenopos.userin clearName of the till or shop, for example Main street shop
currencytextnonenopos.userin clearISO 4217 currency code, for example EUR
receipt_headerlongtextnonenopos.userin clearText printed at the top of receipts
cash_controlboolnonenopos.userin clearWhether sessions must count the cash in the drawer when they open and close
default_opening_cashmoneynonenopos.userin clearCash normally left in the drawer overnight (minor currency units)
allow_refundsboolnonenopos.userin clearWhether cashiers may propose refunds at this point of sale
activeboolnonenopos.userin clearWhether the point of sale is in use

pos_session ​

One shift of selling at a point of sale, from opening to closing the cash drawer

Read group: pos.user. Write group: pos.user.

FieldKindData classPersonal dataGroupAgents seeDescription
config_idref → pos_confignonenopos.userin clearThe point of sale the session belongs to
cashiertextinternalyespos.usermaskedName of the cashier who opened the session
opened_ondatenonenopos.userin clearDay the session was opened (YYYY-MM-DD)
closed_ondatenonenopos.userin clearDay the session was closed (YYYY-MM-DD)
opening_cashmoneyfinancialnopos.userwithheldCash counted in the drawer at opening (minor currency units)
expected_cashmoneyfinancialnopos.userwithheldCash the drawer should hold at closing: opening cash plus cash payments (entered, not computed)
closing_cashmoneyfinancialnopos.userwithheldCash actually counted in the drawer at closing
cash_differencemoneyfinancialnopos.userwithheldClosing cash minus expected cash; negative means money is missing
notelongtextnonenopos.userin clearExplanation for any cash difference
stateselect (open, closed)nonenopos.userin clearSession status: open, closed

pos_order ​

A sale rung up at a point of sale

Read group: pos.user. Write group: pos.user.

FieldKindData classPersonal dataGroupAgents seeDescription
session_idref → pos_sessionnonenopos.userin clearThe session the sale was made in
receipt_numbertextnonenopos.userin clearNumber printed on the receipt. Free text: packages cannot generate sequences
ordered_ondatenonenopos.userin clearDay of the sale (YYYY-MM-DD)
customer_idref → partynonenopos.userin clearThe customer, when one was identified
tax_totalmoneynonenopos.userin clearTax included in the total (minor currency units)
totalmoneynonenopos.userin clearTotal paid by the customer including tax (minor currency units, entered not computed)
notelongtextnonenopos.userin clearRemark about the sale
stateselect (draft, paid, refunded, cancelled)nonenopos.userin clearSale status: draft, paid, refunded, cancelled

pos_order_line ​

One product line of a sale

Read group: pos.user. Write group: pos.user.

FieldKindData classPersonal dataGroupAgents seeDescription
order_idref → pos_ordernonenopos.userin clearThe sale the line belongs to
product_idref → productnonenopos.userin clearThe product sold
descriptiontextnonenopos.userin clearText shown on the receipt
quantitynumbernonenopos.userin clearUnits sold
unit_pricemoneynonenopos.userin clearPrice per unit including tax (minor currency units)
discount_bpnumbernonenopos.userin clearDiscount in basis points: 1000 means 10.00 percent
subtotalmoneynonenopos.userin clearLine total after discount (minor currency units, entered not computed)

pos_payment ​

A payment received against a sale; a sale may be paid with several methods

Read group: pos.user. Write group: pos.user.

FieldKindData classPersonal dataGroupAgents seeDescription
order_idref → pos_ordernonenopos.userin clearThe sale the payment is for
methodselect (cash, card, bank_transfer, voucher, other)nonenopos.userin clearHow the customer paid: cash, card, bank_transfer, voucher, other
amountmoneyfinancialnopos.userwithheldAmount paid with this method (minor currency units)
paid_ondatenonenopos.userin clearDay of the payment (YYYY-MM-DD)
provider_referencetextfinancialyespos.userwithheldReference from the card terminal or payment provider; never a card number

Workflows ​

pos_session ​

ActionMovesWho may run itApproval
pos_session.closestate: open → closedpos.manageryes

pos_order ​

ActionMovesWho may run itApproval
pos_order.paystate: draft → paidpos.userno
pos_order.cancelstate: draft → cancelledpos.userno
pos_order.refundstate: paid → refundedpos.manageryes

Permission groups ​

Groups used by this app:

  • pos.manager
  • pos.user

Approval steps ​

Steps an agent can only propose:

  • pos_session.close
  • pos_order.refund

What agents can and cannot do ​

An agent can read, search, create and update records of this app, and run the actions that need no approval, within the permission groups of its token.

It can only propose these steps, and a person must approve them: pos_session.close, pos_order.refund, pos_config.delete, pos_session.delete, pos_order.delete, pos_order_line.delete, pos_payment.delete.

Personal data is masked as placeholder tokens: pos_session.cashier.

These fields are withheld from agents entirely: pos_session.opening_cash, pos_session.expected_cash, pos_session.closing_cash, pos_session.cash_difference, pos_payment.amount, pos_payment.provider_reference.

Dependencies ​

  • base
  • product

Install ​

Install it from the Customize app (Marketplace), or from the command line:

bash
obop modules install-from pos

Needs a database and administrator rights.

Build your own ​

The module guide shows how apps like this one are written