Skip to main content
All work
POS & KioskWeb + Android

Flashlight Cleanstar

Building a digital workflow for a motorcycle wash, including a public self-service tablet that is not given access to set prices.

Antrian bernomor, shift yang sedang berjalan, dan saldo awal kasir duduk di satu layar. Nomor antriannya dibuat oleh basis data, bukan oleh aplikasi — supaya kios dan kasir tidak bisa mengeluarkan nomor yang sama ketika keduanya menyimpan order pada detik yang sama.
Client
Flashlight Cleanstar — motorcycle wash & detailing, Malang
Industry
Automotive services
Our role
Product definition, system architecture, and development — with the team
Duration
About 5 months (February – July 2026)
Year
2026
StackGoNext.jsFlutterPostgreSQLDocker

Scope at a glance

4

connected apps: kiosk, POS, public site, server

5

screens with distinct jobs, from customer tablet to queue TV

2

branches

0

prices the customer device is able to send

The problem

Nothing was digitised. Transactions, bookkeeping, and order records were all handled by hand, across two branches.

The queue and order log did not have a consistent format. Customers were still informed of their turn by calling out directly.

Helmet, shoe, and apparel cleaning takes days, and customers do not wait on site. Without a trackable record, dropped-off items easily lose their trail — and customers could only phone in to ask whether their things were ready.

The cash drawer often failed to reconcile at closing, with no record to trace the difference against.

The owner did not yet have a view of net profit by service. Without recorded cost prices, revenue alone was not enough to understand margin.

Constraints

  • An unauthenticated tablet stands in a public room. Anyone can touch it, including someone intending to change a price.
  • The shop cannot stop serving customers just because the internet drops.
  • The receipt printer the shop already owned uses a connection browsers do not support, so the path had to run over a USB cable.
  • No payment gateway. Cash and card terminal only, recorded manually by the cashier.

Approach

The customer device is not given access to set prices

An order request from the tablet carries only the identity of the customer, vehicle, service, and additional items. The server determines every amount, while the customer device sends no price field. This separation helps reduce the risk of price changes from the public kiosk.

Queue numbers are issued by the database, not the application

Reading the highest number and adding one can produce duplicates when the kiosk and POS save an order at the same time. Numbering was therefore moved into the database as a single operation, with a uniqueness rule per date.

Every amount is stored as a whole rupiah

Amounts are stored as whole rupiah values, and the database rejects negatives. This helps prevent rounding errors. When a discount is divided across a combined payment, the largest-remainder method keeps the parts aligned with the total.

Cost price is frozen onto every transaction

A service's cost price is copied onto the transaction at the moment it is created, rather than read back from the catalogue when a report is opened. Otherwise raising a price today would silently rewrite last month's profit report. Category names and overnight fees are treated the same way.

The kiosk has to work without internet

The tablet keeps the catalogue on the device and holds unsent orders in a local queue. Once the connection returns, orders are retried automatically while customers see an offline indicator.

Customers check for themselves via a QR code on the receipt

The receipt carries a QR code to a tracking page that needs no login. Customers can check the status of dropped-off items without always phoning the shop, which may reduce status enquiries handled by staff.

Screens

The numbered queue, the shift in progress, and the cashier's opening float sit on one screen. Queue numbers are issued by the database rather than the application — so the kiosk and the POS cannot hand out the same number when both save an order in the same second.
The numbered queue, the shift in progress, and the cashier's opening float sit on one screen. Queue numbers are issued by the database rather than the application — so the kiosk and the POS cannot hand out the same number when both save an order in the same second.
One shift, summarised: wash count by category, cash and card takings, then opening and closing float side by side. A cash difference can be traced to a shift and a person, rather than surfacing as one number that fails to reconcile at closing.
One shift, summarised: wash count by category, cash and card takings, then opening and closing float side by side. A cash difference can be traced to a shift and a person, rather than surfacing as one number that fails to reconcile at closing.

Observed outcomes

The whole shop flow now has a digital form: customers register themselves at the tablet, join a numbered queue, appear on the waiting-room TV, are processed at the POS, and pay with a printed receipt.

Multi-day drop-offs have their own docket number, an estimated ready date, and a tracking link the customer can open at any time.

The closing process now records opening float, cash and card sales, expenses, a physical count by denomination, and any difference with a written reason.

Reports provide profit information alongside revenue, while cost prices are restricted on the server and are not sent to cashiers or ordinary administrators.

An honest note: business impact has not been measured, and this system still lacks adequate automated testing on the interface side. That is open work, not something we are hiding.

Ready when you are / →

Working through a similar need?

Tell us about the situation. Together, we can map the need, possible approaches, and an initial scope.

We usually reply within one business day.