Vai trò Thu Ngân
Thu ngân là người vận hành trực tiếp tại quầy gaming kiosk. Họ sử dụng ứng dụng này trên máy tính bảng Android chuyên dụng đặt tại quầy thu ngân, đóng vai trò cầu nối giữa tiền mặt thực tế và hệ thống credits của người chơi.
Chuyển đổi tiền mặt → Credits
Nhận tiền mặt từ người chơi, nhập số tiền và phương thức thanh toán, hệ thống tự động cộng credits vào tài khoản người chơi.
Thanh toán Credits → Tiền mặt
Khi người chơi muốn đổi credits ra tiền mặt, thu ngân xử lý lệnh redeem và chi tiền trực tiếp tại quầy.
Đếm tiền theo mệnh giá
Mỗi lần mở ca, đóng ca, hay nạp tiền giữa ca đều yêu cầu nhập số lượng từng mệnh giá — đảm bảo tính chính xác và trách nhiệm giải trình.
Quản lý tài khoản người chơi
Tra cứu người chơi qua số điện thoại hoặc username. Tạo tài khoản mới nếu người chơi chưa có — ngay tại quầy, không cần rời đi.
Theo dõi lịch sử ca
Xem lại toàn bộ danh sách ca làm việc của mình, bao gồm tổng giao dịch, số tiền qua quỹ, và trạng thái bàn giao.
Trách nhiệm giải trình
Mọi giao dịch đều được ghi nhận theo ca. Device fingerprint đảm bảo mỗi thiết bị Android đều được định danh duy nhất.
Vòng đời Ca Làm việc
Mỗi ca làm việc đi qua 5 bước có thứ tự bắt buộc. Ứng dụng hướng dẫn thu ngân từng bước và ngăn không cho bỏ qua bước nào.
Mở quỹ đầu ca
Thu ngân đếm toàn bộ tiền trong két trước khi ca bắt đầu. Nhập số lượng từng mệnh giá vào Denomination Grid. Hệ thống tính tổng tự động và tạo bản ghi ca mới.
Ca đang hoạt động
Màn hình làm việc chính. Thu ngân tìm kiếm người chơi, nạp credits, đổi credits, tạo người chơi mới. Danh sách giao dịch của ca hiển thị realtime bên cạnh.
Nạp tiền giữa ca
Khi két cần thêm tiền mặt trong ca, thu ngân ghi nhận lần nạp này bằng Denomination Grid. Mỗi cash drop được ghi lại với đầy đủ chi tiết mệnh giá.
Đóng quỹ cuối ca
Cuối ca, thu ngân đếm lại toàn bộ tiền mặt và nhập vào Denomination Grid. Hệ thống so sánh với số dư kỳ vọng, ghi nhận chênh lệch (nếu có).
Bàn giao ca
Chuyển giao ca cho thu ngân tiếp theo. Bản ghi bàn giao được lưu lại bao gồm thông tin người nhận, ghi chú, và trạng thái két tiền.
* CashDropPage có thể được thực hiện nhiều lần trong một ca, không phải bước bắt buộc. Các bước còn lại phải theo đúng thứ tự.
Denomination Grid — Lưới Đếm Tiền
DenominationGrid.tsx là component trung tâm của ứng dụng — được dùng ở cả 3 trang đếm tiền (Opening, Cash Drop, Closing). Hỗ trợ 7 mệnh giá tờ và 6 mệnh giá xu theo chuẩn USD.
💵 Tờ giấy — BILL_DENOMINATIONS
🪙 Xu — COIN_DENOMINATIONS
Utils — denominations.ts
Lý do dùng Denomination Grid
- Loại bỏ hoàn toàn việc tính nhẩm — thu ngân chỉ cần đếm số lượng tờ/xu
- Tổng tiền được cập nhật tức thì khi nhập số lượng
- Dữ liệu chi tiết theo mệnh giá được lưu cho mục đích kiểm toán
- Phù hợp với quy trình kiểm quỹ chuẩn của ngành
- Hỗ trợ phát hiện chênh lệch khi so sánh Opening vs Closing
Giao dịch với Người Chơi
ActiveShiftPage.tsx là màn hình làm việc chính. Thu ngân thao tác tất cả giao dịch với người chơi từ đây — tìm kiếm, nạp credits, đổi credits, tạo tài khoản mới.
Luồng Nạp Credits (Deposit)
cashierDepositCredits()
Luồng Đổi Credits (Redeem)
cashierRedeemCredits()
Tạo Người Chơi Mới — cashierCreatePlayer()
Component PhoneInput từ @kioskgaming/ui xử lý format số điện thoại chuẩn quốc tế, thu ngân không cần lo về định dạng.
Android Native với Capacitor 7
Ứng dụng được đóng gói thành APK Android qua Capacitor 7, chạy trực tiếp trên máy tính bảng Android chuyên dụng đặt tại quầy. Điều này mang lại trải nghiệm native app trong khi vẫn phát triển bằng React/TypeScript.
@capacitor/android v7
Chuyển đổi React web app thành APK Android native. Codebase duy nhất, triển khai như app Android thực thụ.
Device Fingerprint
deviceFingerprint.ts tạo Device ID duy nhất cho mỗi thiết bị Android. Gắn kết thiết bị với ca làm việc.
CRACO Config
Create React App được mở rộng qua CRACO — thêm alias, plugins Tailwind, cấu hình build tùy chỉnh mà không eject.
Lợi ích của Android Native Shell
- WebView tải nội dung từ
server.urlremote — cần mạng ổn định - Device fingerprint UUID lưu localStorage, gắn ca + đăng ký thiết bị
- APK build qua
npm run apk:dev/apk:prod+ gradlew - Package id:
club.kioskservice.kioskgaming.cashier - Thiết bị mới cần quản lý cửa hàng duyệt trong Shop Portal
- CRACO patch source-map-loader từ
packages/ui/scripts/
capacitor.config.ts
Build flow:
npm run build
→
npx cap sync android
→
npx cap run android
→ APK triển khai lên thiết bị
Bảo mật & Trách nhiệm Giải trình
Ứng dụng thu ngân xử lý tiền mặt thực tế, vì vậy mọi lớp bảo mật và audit trail đều là yêu cầu bắt buộc, không phải tùy chọn.
CashierProtectedRoute
Mọi trang đều được bảo vệ bởi CashierProtectedRoute.tsx. Không có phiên hợp lệ → redirect về trang đăng nhập.
useCashierAuth Hook
Hook riêng biệt useCashierAuth.tsx quản lý trạng thái xác thực, token, và session của thu ngân.
Device Fingerprint
deviceFingerprint.ts tạo Device ID không thể giả mạo. Mỗi ca làm việc được gắn với thiết bị cụ thể.
Denomination Audit Trail
Mọi lần đếm tiền đều lưu chi tiết theo từng mệnh giá. Không thể sửa lịch sử sau khi submit — mọi chênh lệch đều bị phát hiện.
Shift Lifecycle Enforcement
Ứng dụng bắt buộc đi qua đúng thứ tự: Opening → Active → Closing → Handover. Không thể bỏ qua bước nào.
axios Client
cashierApi.ts dùng singleton axios với interceptor Bearer token và bắt 401 → logout. Base URL đã gồm /api.
MyShiftsPage.tsx — Thu ngân có thể xem toàn bộ lịch sử ca của mình: số tiền qua quỹ, tổng giao dịch, trạng thái, và thời điểm bàn giao. Đây là nguồn chứng minh nếu có tranh chấp về tiền.
Technical Stack
Cấu trúc Services
Toàn bộ Pages
| File | Mục đích |
|---|---|
| CashierLoginPage | Đăng nhập thu ngân |
| OpeningCashPage | Đếm tiền mở quỹ |
| ActiveShiftPage | Giao dịch trong ca |
| CashDropPage | Nạp tiền giữa ca |
| ClosingCountPage | Đếm tiền đóng quỹ |
| HandoverPage | Bàn giao ca |
| MyShiftsPage | Lịch sử ca làm việc |
| Thư viện / Tool | Phiên bản | Vai trò |
|---|---|---|
| React | 18 | UI framework chính |
| TypeScript | 4.9 | Type safety cho toàn bộ codebase |
| CRACO | — | Extend CRA config (aliases, plugins) không eject |
| Capacitor | 7 | Android native shell — đóng gói React thành APK |
| @capacitor/android | v7 | Android platform bridge |
| react-hook-form | v7 | Form validation (login, create player, reset password) |
| react-hot-toast | — | Toast notifications cho giao dịch thành công/thất bại |
| Tailwind CSS | 3 | Styling utility-first |
| @kioskgaming/ui | file:../packages/ui | Modal, PhoneInput — shared UI (symlink packages/ui) |
| @kioskgaming/page-loading | file:../packages/page-loading | PageLoadingIndicator cho route guard |
| axios | ^1.3 | HTTP client singleton + interceptors |
Components Chia sẻ