UMKA Laundry
01 — The brief
UMKA Laundry is an industrial laundry that processes large volumes of linens for business customers. The operation ran on manual steps: orders written up by hand, receipts and labels produced ad hoc, and — most painfully — e-waybills and e-invoices typed into a government portal one by one. The brief was to turn the daily workflow into software: take orders, package them, print at the counter, and issue the legal e-documents automatically.
Two things made it harder than a typical CRUD app. Printing had to be instant and silent at a busy counter, on machines shared by several staff. And the e-document lifecycle had to satisfy a government integrator’s rules — drafts, finalisation, submission and status — without a person babysitting each one.
02 — Approach
The backend is a Spring Boot service with JWT authentication and fine-grained method security — close to two hundred authorization rules across five staff roles. Orders can be entered one at a time or imported in bulk from Excel; a packaging workflow moves them to receipts and labels; a daily report is generated and emailed on a schedule.
The e-document lifecycle is automated end-to-end against the Uyumsoft integrator. The system drafts an e-waybill or e-invoice, finalises it and submits it, and a scheduled job polls status every sixty seconds and retries — so what used to be manual portal work is now a self-running pipeline. Printing and shared-machine access needed more than a browser could give, so the panel also ships as an Electron desktop app: it prints receipts silently to a thermal printer, manages print devices and a queue, and adds device-token authentication with a quick-login switcher so staff can hand a shared terminal off in seconds. One React codebase builds both the web panel and the desktop app.
- Backend Spring Boot + JWT — ~197 @PreAuthorize rules, 5 roles
- e-Documents Uyumsoft e-waybill & e-invoice lifecycle + 60s status poller
- Printing Electron silent thermal print (50×80 mm) + ZXing QR labels
- Data in/out Apache POI Excel import · scheduled emailed reports
- Realtime WebSocket / STOMP notifications
- Email Resend (with SMTP fallback)
None of this was free. Each choice bought something and charged for it somewhere else — the work was in choosing where to pay.
-
Trade-off 01
Electron desktop over a browser panel
A shared counter needs silent thermal printing and per-device trust that a browser sandbox won’t allow. Electron delivers both, from the very same React build. The cost is shipping and updating a desktop binary — an installer to maintain alongside the web app.
-
Trade-off 02
Automated e-documents over manual issuing
Turning hand-typed portal work into a drafted, submitted, status-polled pipeline removes the daily bottleneck and the transcription errors. The cost is owning the integrator’s async reality: failures, retries and status drift all have to be handled in code — which is why a job polls every sixty seconds.
-
Trade-off 03
Idempotent hand-migrations over trusting the tool
A duplicate migration version once stopped schema changes from applying and broke a deploy. The response was defensive: idempotent, hand-checked migrations plus a generated audit that diffs the live database against what the code expects. Slower to write, but safe on a system that can’t take downtime.
-
Trade-off 04
Two auth surfaces over one
Staff share terminals, so the desktop adds a device token and a quick-login switcher on top of normal JWT auth. It makes handing off a machine instant. The cost is two authentication paths to keep secure instead of one.
What used to be typed by hand into a government portal is now a scheduled, self-healing pipeline.
03 — Results
UMKA Laundry runs in production. Orders, packaging, receipts and reporting live in one system, and e-waybills and e-invoices that were once issued by hand are now automated, submitted and status-checked without intervention. Counter staff print instantly on shared machines and switch users in seconds.
04 — What’s next
Work in progress moves email fully onto Resend and evaluates a managed Postgres (Supabase) for the datastore, while extending the reporting and the real-time notification system.