Dokumen Teknis

Arsitektur & skema data — sistem analitik toko

Referensi implementasi untuk tim engineering. Versi ringkas non-teknis ada di dokumen terpisah untuk stakeholder bisnis; dokumen lengkap (22 bagian, termasuk seluruh rasional & riset pendukung) ada di README.md project.

Non-realtime / batch CV klasik + VLM sampling Nol Re-ID biometrik
01 — Ringkasan

Dua lapis, dipisah sengaja berdasarkan biaya

Layer 1 (CV klasik) menangani semua tracking dasar secara terus-menerus dan murah. Layer 2 (VLM) cuma dipanggil batch, pada sampel yang relevan. Identitas konsumen tidak pernah di-Re-ID — sesi dilabel ulang ke identitas asli hanya pada titik transaksi/loyalty scan.

Kenapa bukan Re-ID biometrik persisten: bukan cuma soal kepatuhan UU PDP — Re-ID butuh resolusi kamera tinggi, model embedding yang jauh lebih berat, storage yang terus tumbuh, dan matching yang melambat seiring skala. Skema sesi-sekali-pakai + relabel-saat-transaksi lebih murah dan lebih patuh sekaligus. Detail lengkap trade-off ada di README §1 & §20.

02 — Pipeline

Dari kamera sampai insight

Enam tahap, dua di antaranya batch (bukan streaming).

kamera

Buffer lokal

Rekam terus, klip 5–15 menit atau per event masuk/keluar frame. Tidak ada yang dikirim ke model apa pun di tahap ini.

layer 1 · terus-menerus

Deteksi + tracking

YOLOv8n/11n + ByteTrack. Hitung dwell time, deteksi marker warna/ArUco untuk staf, estimasi head-pose kasar untuk proxy viewing time. Tulis ke track_event, zone_dwell_segment, staff_zone_presence.

layer 2 · batch 15–30 mnt

VLM sampling

Cuma track yang lolos threshold (dwell tinggi / ada interaksi tangan-objek) dikirim ke VLM murah untuk label semantik. Tulis ke track_enrichment.

batch harian

Join ke POS

Cocokkan track_event ke transaksi lewat window waktu + counter_id. Hasilkan track_transaction_match (closing/non-closing) dan, kalau ada loyalty_id, backtrack identitas ke member.

batch harian

Scoring & sinyal turunan

Skor komposit staf (staff_score_daily), sinyal minat sekunder (secondary_interest_signal), flag anomali.

output

Dashboard & trigger

Laporan untuk manager/marketing/owner, broadcast WhatsApp otomatis (personalized_offer_log).

03 — Data Model

Video & POS (Layer 1 + 2 + join)

Tabel inti — skema lengkap dengan komentar ada di README §10. Ringkasan kolom kunci per tabel:

track_eventLayer 1 · per sesi kunjungan
track_idpksekali pakai per sesi
store_id, counter_idlokasi
detected_markernull kalau konsumen
entered_at / exited_atrentang sesi
dwell_seconds, gaze_secondstotal sesi
has_hand_object_interactiontrigger Layer 2
track_enrichmentLayer 2 · hasil VLM
track_idfk→ track_event
interaction_typelihat / pegang-coba / ngobrol
product_hintmodel produk terinfer
model_usedaudit biaya/akurasi
zone_dwell_segmentLayer 1 · per zona
track_id, zone_idfkbreakdown per area
entered_at / exited_atper kunjungan ke zona
dwell_secondsSUM boleh > total sesi (bolak-balik)
staff_zone_presenceLayer 1 · coverage staf
cashier_id, zone_iddari marker (§5.6)
entered_at / exited_atdasar response time, idle time, coverage gap
track_transaction_matchJoin layer
track_id, transaksi_idfknull transaksi_id = non-closing
is_closingboolean hasil matching
match_confidenceexact_counter / store_level_fallback
cashier_marker_mapInput manual
marker_codepkwarna/ArUco id
cashier_iddiupdate manual tiap rotasi staf
-- matching logic, dijalankan sebagai batch job harian setelah POS sync
SELECT t.track_id, tx.transaksi_id
FROM track_event t
JOIN transaksi tx
  ON tx.counter_id = t.counter_id
 AND tx.created_at BETWEEN t.exited_at AND t.exited_at + INTERVAL '5 minutes'
WHERE t.store_id = tx.store_id;
04 — Presisi Etalase

Deteksi SKU-level tanpa VLM

README §26. Kamera/sensor kecil per etalase mendeteksi slot kosong/terisi (frame differencing sederhana, bukan klasifikasi visual) — dicocokkan ke track_id lewat timestamp + zona, pola yang sama persis dengan matching di §pipeline.

etalase_slot_definitionMapping manual
slot_id, skupk1 slot = 1 SKU pasti, dari inventori
zone_id→ zone_definition
slot_eventMentah, dari sensor
event_type'lifted' | 'returned'
detected_attimestamp presisi
slot_hold_sessionlifted+returned dipasangkan
lifted_at, returned_atrentang pegang
hold_secondsdihitung otomatis, bukan manual
slot_track_matchJoin ke orang
slot_hold_session_id, track_idfkvia zona+waktu, §5.1
match_confidencesingle_person_in_zone paling andal

Kenapa lebih murah dari Layer 2 VLM, bukan lebih mahal: kamera etalase cuma jawab "slot ini kosong atau tidak" — bukan "ini model apa". SKU sudah pasti dari etalase_slot_definition, jadi product_hint jadi ground truth, menggantikan sebagian kebutuhan VLM (§4) yang sebelumnya menebak dari gambar. Alternatif presisi lebih tinggi: RFID/NFC per unit jam, tanpa CV sama sekali — lihat README §26.4.

05 — Data Model

Gamifikasi (konsumen & staf)

Pelengkap §19 README — 13 tabel total, di sini yang paling sering dipakai. points_ledger adalah satu-satunya sumber kebenaran saldo poin (dihitung dari SUM, bukan kolom terpisah).

memberRegistrasi WhatsApp-first
loyalty_idpksama dgn backtrack §5.3
no_hp, bulan_lahirdata minimal (UU PDP)
deleted_atsoft delete → right to erasure
points_ledgerAppend-only
event_typeearn / redeem / expire / referral
points_delta+/- , saldo = SUM
source_refaudit trail
secondary_interest_signalBatch harian
loyalty_id, track_idfkhanya sesi closing + scan member
zone_id vs purchased_zone_idminat vs yang dibeli
staff_score_dailySnapshot historikal
cashier_id, score_dateunique1 baris per staf per hari
composite_scoreweighted: conversion + basket + approach + diversity

Belum ada di skema — sengaja ditunda: visit_companion_group (deteksi kunjungan berpasangan) butuh data posisi kontinu, bukan cuma entry/exit per zona seperti sekarang — lihat README §21.2 sebelum diimplementasikan.

06 — Program Loyalitas

Siklus servis 6-bulan, poin, tier, trade-in

README §23–§25. Servis baterai gratis dijadwalkan proaktif tiap 6 bulan (bukan menunggu baterai habis) — ini jadi jantung seluruh sistem poin & tier, plus program trade-in/refurbish yang terpisah secara ekonomi.

battery_service_logSiklus 6 bulan
loyalty_id, serviced_atfktiap kunjungan servis
next_due_at= serviced_at + 6 bulan
was_on_timebasis streak, §25.2
battery_reminder_logTrigger reaktivasi
due_at= next_due_at yg memicu
sent_atWA terkirim, biasanya H-7
responded_atnull = belum datang lagi
trade_in_appraisalPenilaian tukar-tambah
watch_model_traded, gradeA / B / C / reject
trade_in_credit≤ target_cogs per grade
photos_refaudit konsistensi grading
refurb_inventoryUnit siap jual
source_appraisal_idfk→ trade_in_appraisal
listed_pricebervariasi per grade, bukan flat
non_exchangeabledefault true — cegah siklus tak berujung

Aturan poin (basis: 1 poin = Rp10.000 spend)

AktivitasPoinevent_type
Servis baterai 6-bulanan+50 flatearn_battery_service
Streak on-time (kunjungan ke-2 berturut)+25, naik bertahap (cap)earn_mission (on_time_streak)
Trade-in diproses+200 flatearn_trade_in
Personalisasi/gravir+30earn_mission
Referral berhasil+100 / +50referral_bonus

Tier — total poin earned, rolling 12 bulan

TierThresholdKira-kira setara
Dasar0+Member baru
Menengah500+~2 servis on-time (1 thn) + 1 pembelian menengah
Utama1.500+Pembelian rutin + servis konsisten + 1 trade-in
Kolektor4.000+Riwayat multi-pembelian/trade-in

Margin refurbish — cek dulu sebelum set harga: pada margin toko ~3x (COGS ≈33% harga jual), diskon flat 50% menyisakan trade-in credit yang terlalu kecil untuk menarik partisipasi. Pakai diskon bertingkat per grade (15–20% / 25–30% / 35–40%) dengan formula trade_in_credit + refurb_cost ≤ target_cogs(grade) — detail perhitungan di README §23.3.

07 — Tech Stack

Pilihan komponen, MVP 1 toko

KomponenPilihanCatatan
Person detection + trackingultralytics YOLOv8n/11n + ByteTrackCPU cukup untuk 1–2 kamera
Marker stafHSV segmentation atau cv2.aruconol biometrik, robust resolusi rendah
VLM Layer 2Gemini Flash / GPT-5-mini / Claude Haiku, atau SmolVLM self-hostmodel-agnostic, tinggal ganti endpoint
DatabaseSQLite (MVP) → Postgres/Supabase (scale)upgrade saat multi-toko
Scheduler batchCron / worker sederhana, interval 15–30 mnttidak perlu infra streaming
Broadcast konsumenWhatsApp Business API + Flowsbukan app proprietary — lihat §keputusan
08 — Fase Implementasi

Urutan build, dari yang paling murah

1–2 mgu

Tier 1 — Traffic & antrean

  • Counting line di pintu + polygon zona kasir
  • Log ke SQLite lokal, rekap harian via cron
  • Validasi akurasi vs hitungan manual sebelum dipercaya
3–4 mgu

Tier 2 — Coverage staf + zone engagement

  • Rollout marker, kalibrasi HSV di kondisi cahaya toko sebenarnya
  • Petakan zona toko manual ke koordinat kamera
  • Aktifkan Layer 2 untuk label produk per zona
30 hari

MVP gamifikasi konsumen (opsional, keputusan terpisah)

  • WhatsApp registration flow, validasi struk manual
  • member, consent_log, points_ledger, redemption_log saja dulu
bertahap

Gamifikasi staf — 3 fase trust-building

  • Observasi (manager saja) → non-finansial (badge) → insentif (dengan jalur banding)
  • Jangan lompat langsung ke fase insentif — README §17.5
09 — Keputusan Desain Kunci

Kenapa dipilih begini, bukan yang lain

Batch, bukan realtime

VLM dipanggil per 15–30 menit pada sampel yang lolos threshold, bukan tiap frame — inti dari kenapa biayanya di bawah Rp150rb/toko/bulan. Lihat README §2–§3.

Sesi sekali-pakai, relabel saat transaksi — bukan Re-ID persisten

Lebih murah (tidak perlu model embedding, storage database wajah yang terus tumbuh) dan lebih patuh UU PDP sekaligus — bukan trade-off. README §1, §5.3, §20.

Marker fisik untuk staf, bukan face recognition

Staf bisa diminta pakai marker (konsumen tidak bisa) — HSV/ArUco jauh lebih murah dan lebih robust di resolusi CCTV standar daripada face embedding. README §5.6.

WhatsApp-first, bukan app proprietary

~31% konsumen enggan unduh app baru (riset chatgpt-1.md). WhatsApp Business API + Flows menghilangkan friksi ini sepenuhnya. README §16-B.

Reward selalu deterministik, tidak pernah random

Mekanik random (lucky wheel dst.) butuh izin Kemensos (Permensos UGB No. 3/2024) + hibah 10% + pajak 25% dari nilai hadiah. Guaranteed reward menghindari proses perizinan ini sejak desain. README §6, §11.

10 — Checklist Integrasi

Yang dibutuhkan dari sisi client sebelum mulai

  • Akses data POS — format & metode (API / export harian / replikasi DB) untuk membangun track_transaction_match
  • POS sudah catat cashier_id per transaksi? Kalau belum, ini prasyarat sebelum breakdown performa per kasir bisa jalan
  • Kamera per-counter atau general per-toko? Menentukan resolusi analisis (per kasir vs per toko/shift)
  • Program loyalty existing — sudah catat identifier (no. HP/kartu) di transaksi POS?
  • Toko pilot pertama untuk validasi sebelum scale ke multi-toko