Lesson 4 / 7 · 10 min
Mini CRM: kontak, order, dan label
Dua tabel lagi dan bot menjadi CRM yang bisa ditanya bisnis. Checkpoint: daftar follow-up nyata dari SQL.
Saat ini percakapan menguap begitu selesai. Dua tabel lagi, contacts dan orders, mengubah bot yang sama menjadi sistem yang menjawab pertanyaan bisnis: siapa pelanggan saya, siapa yang bertanya tapi tak pernah bayar, siapa yang harus di-follow-up hari ini.
Langkah 1: dua tabel (tambah di db.js)
db.exec(
"CREATE TABLE IF NOT EXISTS contacts(" +
" phone TEXT PRIMARY KEY," +
" name TEXT," +
" labels TEXT NOT NULL DEFAULT ''," +
" first_seen INTEGER," +
" last_seen INTEGER);" +
"CREATE TABLE IF NOT EXISTS orders(" +
" id TEXT PRIMARY KEY," +
" phone TEXT NOT NULL," +
" item TEXT, qty INTEGER, total INTEGER," +
" address TEXT," +
" status TEXT NOT NULL DEFAULT 'draft'," +
" created_at INTEGER, paid_at INTEGER);"
);
export function touchContact(phone) {
db.prepare(
"INSERT INTO contacts(phone, first_seen, last_seen) " +
"VALUES (?, unixepoch(), unixepoch()) " +
"ON CONFLICT(phone) DO UPDATE SET last_seen = unixepoch()",
).run(phone);
}
export function addLabel(phone, label) {
const row = db.prepare("SELECT labels FROM contacts WHERE phone = ?").get(phone);
const labels = new Set((row?.labels || "").split(",").filter(Boolean));
labels.add(label);
db.prepare("UPDATE contacts SET labels = ? WHERE phone = ?")
.run([...labels].join(","), phone);
}Langkah 2: buat order saat CONFIRM
// flow.js, inside case "CONFIRM" when the answer is "ya":
import { db, addLabel } from "./db.js";
const orderId = "WA-" + Date.now();
db.prepare(
"INSERT INTO orders(id, phone, item, qty, total, address, " +
"status, created_at) VALUES (?, ?, ?, ?, ?, ?, 'confirmed', unixepoch())",
).run(orderId, session.phone, session.data.item, session.data.qty,
session.data.total, session.data.address);
session.data.orderId = orderId;
addLabel(session.phone, "quoted");Langkah 3: pertanyaan yang kini bisa dijawab
-- who to follow up: confirmed > 1 day, still unpaid
SELECT o.phone, o.item, o.qty, o.total
FROM orders o
WHERE o.status = 'confirmed'
AND o.created_at < unixepoch() - 86400;
-- this week's revenue
SELECT SUM(total) FROM orders
WHERE status = 'paid' AND paid_at > unixepoch() - 7*86400;
-- contacts gone quiet for 30+ days (win-back list)
SELECT phone FROM contacts
WHERE last_seen < unixepoch() - 30*86400;Checkpoint: buat dua pesanan tes, lalu jalankan query follow-up dan lihat keduanya terdaftar. Saat daftar nomor telepon keluar dari sebuah query, Anda punya CRM, kecil, tapi nyata, dan tiap label yang Anda tambah mempertajamnya.
Yang Anda dapatkan
- contacts + orders mengubah percakapan jadi data bisnis yang bisa ditanya
- Order dibuat saat CONFIRM berstatus confirmed; pembayaran membaliknya jadi paid
- Label yang ditempel alur membangun pipeline Anda otomatis
- Tiga query SQL memberi daftar follow-up, omzet, dan win-back
Sumber terkurasi
Referensi pilihan untuk mendalami lebih jauh, direview oleh tim kami.