Gadget Fest Docs Help

Transaction handling

Participants of cashless system:

  • Customer: The end user who loads money to his account (top-up) and makes purchases at the festival.

  • Merchant: The entity that sells products and services to the customer.

  • Festival: The organizer of the event, collects money from the customer and pays the merchant

Money is booked in the system on accounts like a double entry bookkeeping system: Each transaction has a debit and credit side, where the debit side is the account that receives money and the credit side is the account that pays money.

Type of transactions:

  • Top-up: Customer adds money to his account, the money is handled by the festival. Entry from open loop side.

  • Purchase: Customer buys a product or service from a merchant.

  • Chargeback: Customer returns a product or service to a merchant and gets money back.

  • Refund: Festival returns leftover money to the customer. Return to open loop side.

Type of accounts:

  • Customer Account: The account of the customer, where the closed loop balance is stored.

  • Merchant Account: The account of the merchant, where the sales is booked.

  • Top-up Account: The account of the festival, where the money arriving from the open loop side is stored.

  • Fee Account: The account of the festival, where the fees collected by the festival is booked.

Transaction types

Top-up transaction

Transaction item

debit account

credit account

topup

customer

top-up

topup fee

fee

customer

Toup 100 CHF with a topup fee of 5 CHF:

Customer 1 account Topup account Fee account _____________________ _____________________ _____________________ 100 CHF | | 100 CHF 5 CHF | | 5 CHF | |

Purchase (closed loop) transaction

Transaction item

debit account

credit account

purchase

merchant

customer

Purchase 55 CHF:

Customer 1 account Merchant 1 account _____________________ _____________________ | 55 CHF 55 CHF |

Purchase (open loop) transaction

This transaction is used if the customer has not enough money on his closed loop account to pay for the purchase. In this case, the customer can pay directly with a credit card at the time of purchase.

This will be handled by creating two transactions, one top-up and one purchase transaction.

Transaction handling

Transactions can be created:

  • in the backend system: (admin site, background jos) like online top-up, auto top-up, chargeback, admin topup, refund to payment gateway, manual refund.

  • in the terminal: like cash or card top-up, purchase, cash refund.

Identification of transactions:

  • Each transaction has a unique integer ID generated in the backend database once it reaches the backend.

  • Transactions created in the terminal will be identified by assignment id and terminal transaction number ( generated in the terminal as an increasing number), assignment id and terminal transaction number must be unique for each event edition. In this case and RFID tag is also present when the transaction is created. The tag will also create and increasing transaction number tag transaction number, which is supposed to be unique together with the UID for each event edition. However, in case the tag data is corrupt the tag transaction number can be restarted and duplicates might occur, for this uniqueness should not be enforced by backend (we will monitor duplicates to spot issues with on tag data handling).

  • assignment id is a unique ID per event edition, it is generated at the time of assignment of the terminal to an event edition, right after this assignment the terminal database is created and transaction number is set to start at 1.

Terminal data model

This ER diagram describes the tables used to store transactions on the terminal before they are synced to the backend.

TransactionintassignmentIdPKTerminal's unique IDintterminalTransactionNumberPKIncrementing transaction number on the terminalstringrfidUidCustomer's RFID UIDdatetimetransactionTimeTime of the transactionenumtransactionTypee.g. Purchase, RefundintoperatorIdID of the operatorintpositionIdPOS position topup positionenumstatusStatus of transaction in the terminalenumsyncStatusSync status with the backendTransactionItemintassignmentIdPK,FKintterminalTransactionNumberPK,FKintitemNumberPKItem number of the item within the transactionintproductIdProduct's unique IDstringproductNameProduct's name at the time of saleintquantityQuantity of the product solddecimalunitPricePrice per unit at the time of saledecimalvatRateVAT rate at the time of salehas

Terminal transaction handling

Purchase and refund transaction lowering customer account balance with reserve step:

Local snapshotBackendTerminal DatabaseRFID tagLocal snapshotBackendTerminal DatabaseRFID tagOperator starts a transactionon the terminalRead UID and next transaction numberand offline data from RFID tagBackend stores offline data in dbquery updated online info for UIDlookup last known info for UID combine with offline dataalt[online][offline]update offline data with new infoand mark offline data as synced (if online)Create transaction and transaction itemsin the terminal database with nextterminalTransactionNumber and tagTransactionNumberstate: OpenBackend checks if the customer has enough balanceand reserves the amount for the transactioncreate transaction in ReservePending stateupdate state to TerminalConfirmStartedupdate state to Abortedalt[reserve ok][insufficient balance]update state to TerminalConfirmStartedalt[online][offline (already offline state or general error during api call)]check same uid and next transaction number,write transaction to tagupdate balance and last transaction numbercontinue untill sucess or cancel by operatorupdate transaction state to CommittedThe transaction detail will be replicated in backgroundFINISH OKupdate transaction state to Aborted, log tap details (tag read, write if any)alt[second tap ok][operator cancel (only possible before write to tag complete)]loop[Create transaction and confirm (each iteration must create a new transaction!!)]OperatorFirst tap RFID tagquery backend for online info, send offline dataReturn updated online info for UID (balance, vouchers, types, statuses, ac zone, etc.)query local snapshot for last known online infoReturn updated online info for UID (balance, vouchers, types, statuses, ac zone, etc.)Return UID and next transaction numberOperator enters transaction detailslike product, quantity, price, etc.Operator start transaction completioncall backend to reserve amount from balanceonline info for UIDinsufficient balance, online info for UIDrestart loop, or finish with abortSecond tap RFID tagcommit transactioncancellOperator

Transaction states (terminal)

State

Description

can be replicated

Open

The transaction has been created

no

TerminalConfirmStarted

Checkout started

no

TerminalConfirmUnknown

Indeterminate state (crash)

yes

Committed

Transaction complete

yes

Aborted

yes

Create transaction, initial state

Start transaction completion

Abort transaction

Commit transaction

Abort transaction

Move to unknown state on cleanup

Open

TerminalConfirmStarted

Aborted

Committed

TerminalConfirmUnknown

We have to implement a cleanup procedure to handle transactions that are in the TerminalConfirmStarted state but not yet confirmed or aborted. This can happen if the terminal crashes. Normally the transaction will be either committed or aborted. The cleanup procedure should be run at startup of the terminal, before each purchase before exit of the terminal.

Transaction states (backend)

State

Description

balance

Open

The transaction has been created

TerminalConfirmUnknown

The terminal has started second tap but no result is available

ReservePending

Reserved at terminal checkout, can be aborted or released after timeout

Reserve from customer

Reserve

Reserved based on uploaded tag data, can not be aborted, no timeout

Reserve from customer

ReserveExpired

ReservePending has not been confirmed with a full transaction

ExternalPending

The open loop payment in top-up is in an indeterminate state, checking for update

ExternalUnknown

The open loop payment in top-up is in an indeterminate state, no more checking

Commited

The transaction is fully booked

Booked

Aborted

Failed or not finished transaction

Online and auto top-up:

Create transaction, initial state

Set before starting transaction at payment gateway (redirect or api call)

Positive response from payment gateway

Negative response from payment gateway (not general error)

Indeterminate or no response from payment gateway

after timeout for background check

Open

ExternalPending

Committed

Aborted

ExternalUnknown

Purchase at terminal:

Replicate transaction

Replicate transaction

online reserve at terminal checkout

Offline tag data uploaded

Offline tag data uploaded

after timeout

Replicate transaction

Replicate transaction (operator cancel)

Replicate transaction

Replicate transaction

Replicate transaction (operator cancel)

Commited

Aborted

ReservePending

Reserve

ReserveExpired

Transaction replication

The terminal will replicate transactions to the backend in the background, this can happen after the transaction is committed or aborted. The backend receiving replicated transaction should check the above logic and only accept the transaction based on the above transitions. Invalid state transitions should be stored to a log table. and an error

10 July 2025