Pada Proyek: Pemrosesan Data dengan Spark kita berhenti pada berkas hasil olahan yang siap diolah lebih lanjut; sekarang kita menuntaskan rantainya sampai dashboard yang dibaca tim manajemen. Dashboard yang gagal hampir selalu gagal pada tahap yang sama dengan gudang data: tim data langsung menggambar grafik tanpa menuliskan pertanyaan apa yang harus dijawab. Pada bagian ini kita membalik urutan tersebut: pertanyaan bisnis ditulis lebih dulu, lalu diturunkan menjadi spesifikasi metrik pada models/metric_definitions.yaml. Berkas itulah yang menjadi kontrak bagi delapan bagian selanjutnya. Pendekatannya mengikuti chapter Semantic Layer: definisi metrik disimpan sebagai kode, bukan hidup di kepala satu orang analis.
Pertanyaan Bisnis yang Harus Dijawab Dashboard #
Tim manajemen TokoKita memberi enam pertanyaan yang harus terjawab oleh dashboard penjualan. Kita catat beserta sumber data dan tabel analitik yang akan menjawabnya:
| Pertanyaan bisnis | Sumber data | Tabel analitik |
|---|---|---|
| Berapa GMV setiap hari sepanjang periode? | pesanan | mkt_gmv_harian |
| Kategori produk mana yang menyumbang GMV terbesar? | pesanan | mkt_kategori |
| Siapa pelanggan paling bernilai dan ada berapa pelanggan aktif? | pesanan | mkt_pelanggan |
| Berapa banyak kunjungan web yang berujung pembelian? | events | mkt_funnel |
| Produk mana yang paling laku dilihat dari item dan GMV? | pesanan | fct_pesanan |
| Berapa porsi pesanan yang dibatalkan? | pesanan | fct_pesanan |
Dua hal langsung terlihat dari tabel di atas. Pertama, satu pertanyaan bisa dijawab lebih dari satu tabel, tetapi setiap kolom pengukuran hanya boleh punya satu definisi; itulah alasan definisi metrik harus ditulis sebelum tabel dibuat. Kedua, funnel membutuhkan data event web, bukan hanya pesanan, sehingga sejak awal kita tahu pipeline harus menggabungkan dua sumber.
Menetapkan Kosakata Status #
Sumber pesanan memakai tiga status dalam Bahasa Indonesia yang kita pertahankan konsisten dengan sisa course: selesai, dibatalkan, dan dikembalikan. GMV hanya menghitung pesanan berstatus selesai; pesanan dikembalikan tetap disimpan sebagai transaksi berstatus khusus, bukan dihapus, agar analisis retur tetap mungkin di masa depan. Nilai status di luar kosakata ini, misalnya batal, ditolak ke karantina pada Bagian 3 — kosakata adalah gerbang mutlak.
Menyusun Definisi Metrik #
Definisi keenam metrik kita simpan pada models/metric_definitions.yaml. Cuplikan berikut memuat bagian awal berkas; tiga entri pertama ditampilkan utuh agar polanya terlihat:
# Definisi metrik dashboard penjualan TokoKita.
# Satu sumber kebenaran bagi seluruh angka pada dashboard; pendekatan ini
# meniru semantic layer yang dibahas pada chapter *Semantic Layer*.
versi: 1
model_fact: fct_pesanan
model_funnel: mkt_funnel
status_valid: [selesai, dibatalkan, dikembalikan]
metrik:
- nama: gmv
label: GMV
deskripsi: Nilai penjualan pesanan berstatus selesai
ekspresi: SUM(total)
filter_status: [selesai]
satuan: rupiah
- nama: jumlah_pesanan_selesai
deskripsi: Banyaknya pesanan unik berstatus selesai
ekspresi: COUNT(DISTINCT pesanan_id)
filter_status: [selesai]
satuan: pesanan
- nama: pelanggan_aktif
deskripsi: Pelanggan unik dengan minimal satu pesanan selesai pada periode data
ekspresi: COUNT(DISTINCT pelanggan_id)
filter_status: [selesai]
satuan: pelangganBerkas lengkapnya memuat enam entri; tiga entri berikutnya adalah nilai_pesanan_rata_rata, tingkat_pembatalan, dan konversi_pembelian. Mari kita telaah struktur setiap entri:
namadanlabel: pengenal metrik;labeldipakai saat metrik ditampilkan pada kartu KPI dashboard.ekspresi: agregasi SQL atas kolomfct_pesanan; Bagian 7 memeriksa setiap metrik dihitung ulang lewat jalur independen.filter_status: filter yang melekat pada definisi, sehingga GMV tidak mungkin dihitung dengan cara berbeda oleh dua orang analis.turunandanrumus: metrik sepertinilai_pesanan_rata_ratatidak punya ekspresi SQL sendiri, melainkan rumus atas metrik lain, misalnyagmv / jumlah_pesanan_selesai.sumber:konversi_pembelianmerujukmkt_funnel, bukanfct_pesanan, karena funnel dihitung dari event web.
Memvalidasi Struktur Definisi #
Kesalahan ketik pada berkas definisi harus terdeteksi sejak awal, bukan saat dashboard menampilkan angka yang tidak masuk akal. Skrip kecil berikut membaca berkas tersebut dan memeriksa strukturnya:
import yaml
definisi = yaml.safe_load(open("models/metric_definitions.yaml", encoding="utf-8"))
print(f"model fact : {definisi['model_fact']}")
print(f"model funnel : {definisi['model_funnel']}")
print(f"status valid : {definisi['status_valid']}")
print(f"jumlah metrik : {len(definisi['metrik'])}")
for metrik in definisi["metrik"]:
sumber = metrik.get("ekspresi", metrik.get("rumus", "?"))
print(f" - {metrik['nama']:26s} {sumber}")
assert definisi["model_fact"] == "fct_pesanan"
assert len(definisi["metrik"]) == 6
print("validasi struktur: lulus")Output yang Dihasilkan:
model fact : fct_pesanan
model funnel : mkt_funnel
status valid : ['selesai', 'dibatalkan', 'dikembalikan']
jumlah metrik : 6
- gmv SUM(total)
- jumlah_pesanan_selesai COUNT(DISTINCT pesanan_id)
- pelanggan_aktif COUNT(DISTINCT pelanggan_id)
- nilai_pesanan_rata_rata gmv / jumlah_pesanan_selesai
- tingkat_pembatalan pesanan_dibatalkan / pesanan_total
- konversi_pembelian sesi_tahap_purchase / sesi_tahap_view_product
validasi struktur: lulusBagian 8 kelak menampilkan keenam metrik tersebut sebagai kartu KPI dengan angka nyata hasil pipeline, jadi setiap nama di berkas definisi akan muncul kembali sebagai kunci pada data.json.
Enam definisi terbaca utuh dan dua asersi lulus. Angka aktual seperti total GMV belum muncul di sini karena memang belum ada data yang diolah — itulah justru intinya: kontrak metrik berdiri sebelum data mengalir.
Daftar Periksa Kebutuhan #
Sebelum lanjut, kita pastikan keputusan bagian ini sudah mengikat:
- enam pertanyaan bisnis tercatat beserta sumber dan tabel analitiknya,
- kosakata status ditetapkan:
selesai,dibatalkan,dikembalikan, - enam metrik terdefinisi pada
models/metric_definitions.yaml, dan - dua sumber data teridentifikasi: ekspor pesanan CSV dan event web JSON Lines.
Dengan kontrak metrik yang mengikat, kita siap mengumpulkan data dari kedua sumber pada Bagian 2.