My bachelor thesis: a mobile payment and loyalty app for the people buying from vending machines, and for the people refilling them.
TypeScript
Prisma
Checkout orchestration
Data analysis
01 / The problem
Tapping a card already works. An app has to beat that.
Vending machines already have card terminals, and tapping one takes about two seconds. That's a hard baseline to beat. What it costs the operator in transaction fees is invisible to the customer, so there's no reason for them to care. The thesis asked whether mobile payment plus loyalty rewards you can actually see would be worth switching for, without burying people in registration steps and reward rules on the way there.
7.4Mhistorical vending sale rows analyzed
02 / Architecture
One backend behind both apps, with the machines and the payment provider kept at arm's length.
Customer and refiller interfaces share contracts with a backend that centralizes machines, inventory, products, campaigns, loyalty, and purchasing. Persistent storage and replaceable payment and dispensing adapters sit at the infrastructure boundary, allowing the clients and external integrations to evolve without moving core business rules out of the application.
03 / Engineering
The decisions behind the system.
01
Campaign optimization algorithm
Two campaigns can want the same can of soda. Take the biggest looking discount first and you can easily end up charging more than you should have.
Implementation details
Cart units are represented as grouped product quantities rather than expanded individual objects
A memoized recursive search evaluates valid, non-overlapping campaign assignments
The grouped state avoids the previous unit-level 2ⁿ growth while preserving the best valid discount
01Setup — grouped quantities expose competing campaign claims.02Search — recursive branches converge on a memoized state.03Result — the best non-overlapping assignment saves 42 kr.
02
Checkout with mocked edges
The server decides what everything costs and what happens next. Payment and the machine itself sit behind interfaces, so either can be swapped for a real provider later.
Implementation details
The server recomputes prices and chooses the best campaign assignment before payment
The use case reserves payment, invokes dispensing, updates inventory and payment state, and returns item-level results
Mock services implement the same interfaces intended for future providers, keeping integration changes at the edges
Checkout / Mocked-edges walkthrough01 / 03
01Authority — the server verifies the cart, stock, and pricing before any money moves.02Orchestration — one jammed unit becomes an item-level partial result and proportional refund.03Replaceability — stable interfaces keep payment and machine integrations at the edges.
04 / Product walkthrough
VEND & GO / MOBILE FLOWSELECT · BROWSE · CHECKOUT
01 Select a machine
→
02 Browse offers
→
03 Checkout and points
05 / Evaluation
We tested a working app, not a mockup.
Instead of putting a static design in front of people, we tested a real app wired to its backend, loyalty logic, campaign system, and database. Participants could complete an actual purchase and watch real prices, real discounts, and real points land.
The buying part worked. Registration and some of the loyalty concepts didn't land as clearly as we'd hoped. The survey and the sales data filled in the rest: what puts people off signing up, which rewards they actually want, and how differently machines behave depending on where they're standing.
06 / Outcome
A prototype complete enough to test, and built so it could keep going.
Vend & Go ties both apps to one backend handling campaigns, loyalty, checkout, inventory, and storage. The sales analysis turned into something separate and more interesting on the side: a starting point for tools that could tell refillers which discounts to run and when to run them.
Delivered
A working customer app, a refiller interface, the backend behind both, the campaign and loyalty system, checkout, and the data layer underneath.
Validated
Picking a machine, browsing products, and checking out mostly made sense to people once they had the real app in their hands.
Next
Wire up real payment and dispensing providers, cut registration down, and make the loyalty rewards easier to understand.