Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Hong Kong Karaoke — Sistem Booking Room Booking room karaoke untuk staf/kasir, berjalan di Vercel (Go serverless), data disimpan di Google Sheets, dan timer + alarm di TV setiap room.查看完整 README ↗
Booking room karaoke untuk staf/kasir, berjalan di Vercel (Go serverless), data disimpan di Google Sheets, dan timer + alarm di TV setiap room.
| Bagian | Lokasi | Keterangan |
|---|---|---|
| Halaman staf | / (public/index.html) | Login username + PIN, jadwal per room, booking, check-in, perpanjang, check-out, batal, laporan, aktivitas, kelola room & user |
| Halaman TV | /tv?room=R01&key=... (public/tv.html) | Sisa waktu, peringatan 5 menit, alarm saat waktu habis |
| API | /api/* (api/index.go → pkg/httpapi) | Satu Go function di Vercel |
| Aturan bisnis | pkg/booking | Harga, cek bentrok, status, laporan |
| Penyimpanan | pkg/sheetstore | Google Sheets API |
| Aplikasi Android TV | android-tv/ | APK WebView fullscreen, auto-start saat TV nyala |
#1E3A8A, font Inter,
menu di sidebar kiri (di HP menjadi menu lipat lewat tombol ☰).public/index.html, public/tv.html,
public/css/app.css (--brand) dan public/css/tv.css.Tombol WhatsApp di setiap booking (kartu, detail timeline, tab Daftar, kartu pengingat) membuka dialog pratinjau: nomor tujuan, jenis pesan, dan isi pesan yang bisa diedit. Buka WhatsApp membuka chat tamu di WhatsApp Web/Desktop/HP kasir dengan pesan terisi; staf menekan Kirim di WhatsApp. Sistem ini tidak mengirim pesan sendiri.
0812… → 62812…, +62 … → 62…). Jika kolom HP
kosong tetapi nomor terketik di kolom Nama, nomor itu dipakai.| Aksi | Staff | Supervisor | Admin | Accounting |
|---|---|---|---|---|
| Lihat jadwal & daftar booking | ✓ | ✓ | ✓ | ✓ |
| Booking baru, check-in, perpanjang, check-out | ✓ | ✓ | ✓ | |
| Konfirmasi Tentative, batalkan Tentative | ✓ | ✓ | ✓ | |
| Batalkan booking Confirm | ✓ | ✓ | ||
| Booking Compliment (gratis, alasan wajib) | ✓ | ✓ | ✓ | |
| Check-out lebih awal, tagih sesuai pemakaian | ✓ | ✓ | ||
| Laporan (harian atau rentang tanggal), log aktivitas | ✓ | ✓ | ✓ | |
| Kelola room (tambah, ubah nama, aktif/nonaktif) dan tabel harga | ✓ | |||
| Kelola user (tambah, ubah role, nonaktifkan, reset PIN) | ✓ | |||
| Kelola TV (buat kode pairing, cabut TV) | ✓ | |||
| Unduh CSV (daftar booking, laporan) | ✓ | ✓ | ✓ |
= + - @ diberi
tanda ' agar tidak dijalankan sebagai rumus di Excel. Setiap unduhan
tercatat di Aktivitas. Jika Excel menampilkan semua kolom dalam satu kolom
(pengaturan wilayah Indonesia memakai ;), buka lewat Data → From Text/CSV
dan pilih pemisah koma, atau buka di Google Sheets.111111) atau berurutan (123456) ditolak.Users kosong, login dengan username admin
dan PIN = ADMIN_PIN. Akun admin itu langsung tersimpan di sheet; ganti PIN-nya
setelah login. Jika semua admin terkunci, kosongkan isi tab Users (sisakan
header) untuk memakai ADMIN_PIN lagi.Log aktivitas (tab Activity): login, ganti/reset PIN, booking baru,
check-in, perpanjang, check-out, batal, perubahan room dan user, lengkap
dengan waktu, username, dan detail (mis. tarif Rp100.000 -> Rp120.000).
Booking juga menyimpan created_by, confirmed_by, checked_in_by, checked_out_by, cancelled_by, dan hold_until (batas tahan Tentative).
tentative ──konfirmasi──> booked (Confirm) ──check-in──> checked_in ──check-out──> finished
│ │ └─ +30 / +1 jam (perpanjang)
└──batal──> cancelled <───┘ batal
Confirm (booked di sheet): booking pasti.
Tentative: belum pasti, menahan slot sampai hold_until = 2 jam sebelum
jam mulai (minimal 30 menit dari saat dibuat, tidak lewat jam mulai). Setelah
itu tampil Kedaluwarsa dan slot terbuka untuk tamu lain. Booking
kedaluwarsa masih bisa dikonfirmasi jika slotnya masih kosong. Tentative harus
dikonfirmasi dulu sebelum check-in, dan tidak bisa diperpanjang.
Compliment (gratis): staff, supervisor & admin; alasan wajib diisi.
Statusnya Confirm, total Rp 0 termasuk perpanjangan; harga normal tetap
disimpan. Laporan menampilkan jumlah, jam, dan nilai normal compliment
(tidak masuk pendapatan); CSV punya kolom compliment, alasan_compliment,
nilai_normal. Tercatat di Aktivitas beserta alasannya.
Kolom Nomor voucher wajib diisi untuk setiap compliment: disimpan
huruf besar, satu voucher hanya untuk satu booking yang tidak dibatalkan
(dibatalkan → voucher bisa dipakai lagi), bisa dicari di tab Daftar, ikut di
CSV (voucher) dan Aktivitas.
Check-out lebih awal: jika tamu check-out sebelum jam selesai, muncul pilihan tagihan:
billed_minutes di tab Bookings.
Booking compliment tetap Rp 0. Laporan "Jam terpakai" memakai waktu
check-in s/d check-out sebenarnya; CSV punya kolom menit_pakai dan
menit_ditagih.Tab Daftar: semua booking dengan filter status (Confirm, Tentative, Tentative kedaluwarsa, Cancel, Check-in, Selesai), rentang tanggal mulai (maks. 92 hari, default hari ini + 30 hari), dan pencarian nama/HP/catatan. Menampilkan jumlah dan total harga, serta tombol aksi di tiap baris.
Harga (menu Harga, tab Pricing), sama untuk semua room:
| Hari | Mulai 11:00 – 16:59 | Mulai 17:00 – 10:59 |
|---|---|---|
| Senin – Kamis | Rp 60.000 / jam | Rp 120.000 / jam |
| Jumat – Minggu | Rp 85.000 / jam | Rp 170.000 / jam |
| Kondisi | Tampilan | Suara |
|---|---|---|
| Tamu sudah check-in | Nama tamu, hitung mundur besar, progress bar | – |
| Sisa ≤ 5 menit | Angka dan banner oranye "Waktu tinggal N menit" | Chime 2× (sekali per jam selesai) |
| Waktu habis | Layar merah berkedip "WAKTU HABIS" | Sirene berulang tiap 2,5 detik |
Alarm waktu habis berbunyi terus sampai staf check-out atau perpanjang di halaman staf. Tombol "Senyapkan 2 menit" di TV hanya menunda; setelah 2 menit alarm bunyi lagi. Setelah perpanjang, peringatan 5 menit akan muncul lagi untuk jam selesai yang baru.
Pengingat di halaman staf/kasir (semua role, di tab mana pun): halaman staf memantau semua room yang sedang check-in hari ini (tiap 15 detik).
⏰ (2) Hampir habis agar terlihat dari jendela lain.chrome.exe --autoplay-policy=no-user-gesture-required --app=https://sistembookingkaraoke.vercel.app
(tutup semua jendela Chrome dulu), atau minta IT menambahkan alamat ini ke
kebijakan Chrome/Edge AutoplayAllowlist.TV mengambil status dari server tiap 20 detik (10 detik saat peringatan/alarm), dan menghitung mundur sendiri tiap detik memakai jam server. Jika internet putus, timer tetap berjalan dan alarm tetap bunyi.
Buat spreadsheet kosong di Google Sheets. Salin ID dari URL:
https://docs.google.com/spreadsheets/d/<SPREADSHEET_ID>/edit
Share spreadsheet ke email service account ([email protected])
sebagai Editor.
Buat tab dan header otomatis (opsi -seed menambah 4 contoh room):
# isi .env (lihat .env.example), GOOGLE_SERVICE_ACCOUNT_FILE=/path/ke/key.json
set -a; . ./.env; set +a
go run ./cmd/sheetsetup -check # hanya membaca: daftar tab
go run ./cmd/sheetsetup -seed # buat tab + 4 contoh room
Perintah ini hanya menambah tab yang belum ada; data yang sudah ada tidak diubah.
Struktur sheet (baris 1 = header, kolom dicari berdasarkan nama header):
id | name | rate_per_hour | active — sebaiknya diubah lewat
menu Room (admin) supaya tercatat di log; edit langsung di sheet tetap bisa.id | room_id | customer_name | phone | start | end | duration_minutes | status | rate_per_hour | total_price | notes | checked_in_at | checked_out_at | created_at | updated_at | created_by | checked_in_by | checked_out_by | cancelled_by | confirmed_by | hold_until | complimentary | compliment_reason | billed_minutes | voucher_number
— diisi oleh aplikasi. Waktu dalam WIB, format YYYY-MM-DD HH:MM.
Boleh menambah kolom sendiri di kanan; isinya tidak akan ditimpa.username | name | role | pin_hash | active | created_at | updated_at
— kelola lewat menu User. pin_hash tidak bisa dibalik menjadi PIN tanpa
PIN_PEPPER yang hanya ada di server. Batasi siapa yang bisa membuka spreadsheet.time | username | action | booking_id | room_id | detail — hanya ditambah, jangan diedit.day_type | start | end | rate_per_hour — weekday/weekend,
jam HH:MM; jam selesai lebih kecil dari jam mulai = melewati tengah malam.
Ubah lewat menu Harga (admin), yang memeriksa setiap jenis hari menutup
24 jam tanpa tumpang tindih.id | name | room_id | status | token_hash | pair_code_hash | pair_expires | created_by | created_at | paired_at | revoked_by
— TV yang dipasangkan; kelola lewat menu TV, jangan diedit.Setelah update aplikasi yang menambah kolom/tab, jalankan lagi
go run ./cmd/sheetsetup -check lalu go run ./cmd/sheetsetup. Perintah ini
hanya menambah tab dan kolom di ujung kanan; data lama tidak diubah.
Jangan ubah nama header atau isi kolom
id. Hindari mengedit baris booking yang sedang aktif langsung di sheet; pakai halaman staf.
Push folder ini ke Git (GitHub/GitLab), lalu Import Project di Vercel. Framework preset: Other. Tidak perlu build command.
Set Environment Variables (lihat .env.example):
| Nama | Isi |
|---|---|
ADMIN_PIN | PIN untuk login pertama sebagai admin (6-12 angka) |
SESSION_SECRET | openssl rand -base64 48 |
PIN_PEPPER | openssl rand -base64 48 — jangan pernah diganti setelah ada user |
TV_KEY | openssl rand -hex 16 |
SPREADSHEET_ID | ID spreadsheet |
GOOGLE_SERVICE_ACCOUNT_JSON | isi file JSON, atau base64-nya: base64 -i key.json |
APP_TIMEZONE | opsional, default Asia/Jakarta |
Deploy. Cek https://<app>.vercel.app/api/health → {"ok":true,...}.
Buka https://<app>.vercel.app/, login dengan PIN.
Pairing (cara utama). Setiap TV mendapat kunci sendiri; tidak perlu mengetik kode room atau TV key.
/tv di browser TV). Layar
Pengaturan TV meminta kode pairing; ketik 6 angka itu dengan remote.TV yang hilang, rusak, atau dipindah ruangan: menu TV → Cabut. TV itu
kembali ke layar pairing; TV lain tidak terpengaruh. Kode yang belum dipakai
bisa dibatalkan dengan tombol yang sama. Semua kejadian tercatat di Aktivitas.
Server hanya menyimpan hash kode dan hash token (tab Devices). Salah kode 10
kali dari alamat yang sama mengunci pairing dari alamat itu selama 10 menit.
Cara lama (masih didukung): kode room + TV_KEY bersama, lewat
/tv?room=R01&key=<TV_KEY> atau tautan "Cara lama" di layar pengaturan.
Opsi A – Browser TV / mini PC / Chromecast dengan browser:
buka https://<app>.vercel.app/tv dalam mode fullscreen, lalu masukkan kode pairing.
Tekan OK sekali saat muncul "Tekan OK untuk mengaktifkan suara" (aturan
autoplay browser). Pengaturan tersimpan di TV; buka /tv?setup=1 untuk mengubah.
Opsi B – Aplikasi Android TV (disarankan untuk Android TV / TV box): suara alarm langsung aktif tanpa tekan tombol, layar tidak mati, dan aplikasi terbuka sendiri setelah TV dinyalakan. Alamat server sudah terisi otomatis.
Build APK rilis (ditandatangani dengan release key; nilai KARAOKE_TV_* ada di .env):
set -a; . ./.env; set +a
cd android-tv
JAVA_HOME=/opt/homebrew/opt/openjdk@17 ./gradlew assembleRelease
# APK: android-tv/app/build/outputs/apk/release/app-release.apk
Simpan cadangan keystore
~/.config/karaoke-tv/release.jksbeserta password-nya (di.env) di tempat aman, misalnya password manager. Android hanya mau memasang update yang ditandatangani dengan key yang sama; jika key hilang, aplikasi di setiap TV harus di-uninstall dulu sebelum versi baru dipasang.
Pasang ke TV:
Di TV: Settings → Device Preferences → About, klik Build 7 kali untuk membuka Developer options. Lalu Developer options → aktifkan USB debugging / Network debugging (ADB). Catat IP TV (Settings → Network).
Dari komputer di jaringan yang sama:
adb connect <IP-TV>:5555 # setujui prompt "Allow debugging" di TV
adb install -r android-tv/app/build/outputs/apk/release/app-release.apk
# Izinkan auto-start setelah TV dinyalakan (Android 10+):
adb shell appops set com.sentineltech.karaoketv SYSTEM_ALERT_WINDOW allow
adb shell monkey -p com.sentineltech.karaoketv 1 # buka aplikasinya
Aplikasi langsung membuka layar pairing (alamat server sudah terisi). Ketik kode 6 angka dari menu TV di halaman admin.
Cara lama: tekan lama BACK untuk membuka pengaturan aplikasi, isi kode room
dan TV key (adb shell input text "$TV_KEY" untuk mengetik key dari komputer).
Tanpa adb (mis. TV tanpa Developer options): salin APK ke flashdisk, buka dengan
aplikasi file manager di TV, izinkan Install unknown apps, lalu masukkan
kode pairing dengan remote. Auto-start setelah boot butuh langkah appops di atas.
Buka pengaturan lagi: tekan lama BACK atau tekan MENU. Tombol BACK biasa diabaikan supaya tamu tidak keluar dari timer.
Update aplikasi: naikkan versionCode di android-tv/app/build.gradle.kts,
build ulang, lalu adb install -r lagi (pengaturan di TV tetap tersimpan).
# Tanpa Google Sheets (data di memori, hilang saat server berhenti):
STORE=memory ADMIN_PIN=112233 \
SESSION_SECRET=dev-secret-dev-secret-dev-secret-123 \
PIN_PEPPER=dev-pepper-dev-pepper-dev-pepper-12 TV_KEY=dev-tv-key-123456 \
go run ./cmd/devserver
# Login: username admin, PIN 112233
# Staf: http://localhost:8080 TV: http://localhost:8080/tv?room=R01&key=dev-tv-key-123456
go test ./... # unit test aturan booking, auth, parsing sheet, API
vercel build # cek build Vercel secara lokal (perlu `vercel link`)
POLL_MS di public/js/tv.js atau
pindahkan ke PostgreSQL (cukup buat implementasi booking.Store baru).Bookings lama (misal per tahun)
ke spreadsheet lain agar baca tetap cepat.Harga per jam ditentukan oleh jam mulai; seluruh durasi dan perpanjangan
memakai harga itu (16:00–18:00 hari kerja = 2 × 60.000). Hari dihitung dari
tanggal kalender jam mulai (Kamis 23:30 = Senin–Kamis; Jumat 00:30 =
Jumat–Minggu). Di tab Pricing, weekday = Senin–Kamis dan weekend =
Jumat–Minggu. Durasi kelipatan 30 menit,
maks 12 jam. Harga dikunci saat booking dibuat, jadi perubahan harga tidak
mengubah booking lama. Jika tab Pricing dikosongkan, tarif per room di tab
Rooms dipakai lagi.
Booking tidak boleh bentrok dengan booking aktif lain di room yang sama. Perpanjang juga dicek bentrok dengan booking berikutnya.
Check-in paling cepat 60 menit sebelum jam mulai, dan hanya jika room tidak sedang dipakai tamu lain yang belum check-out.
Laporan bisa untuk satu hari atau rentang tanggal (maks. 92 hari), dengan pilihan cepat Hari ini / Kemarin / 7 hari terakhir / Bulan ini / Bulan lalu. Menampilkan total, rincian per room, dan rincian per hari; Unduh CSV mengikuti rentang yang dipilih.
Laporan menghitung booking berdasarkan tanggal mulai. Pendapatan =
booking finished + checked_in. Confirm yang belum check-in dan Tentative
dihitung terpisah, tidak masuk pendapatan.