Impor & Deduplikasi Kontak
OmniStream menyediakan wizard impor CSV bertahap dan alat deduplikasi untuk menjaga direktori kontak tetap bersih. Semua fitur ini memerlukan izin contacts.manage (peran Admin).
Impor Kontak via CSV
Rute frontend
/contacts/import-wizard
Langkah-langkah wizard
Wizard terdiri dari empat tahap berurutan:
| Tahap | Label | Keterangan |
|---|---|---|
| 1 | Upload | Pilih file .csv dari perangkat Anda |
| 2 | Map Columns | Petakan setiap kolom CSV ke field kontak |
| 3 | Preview | Tinjau 5 baris pertama sebelum mengeksekusi |
| 4 | Done | Ringkasan hasil impor |
Tahap 1 — Upload
Klik Choose File dan pilih file CSV (format text/csv). File langsung dibaca di browser (tidak diunggah ke server dulu). Jika file tidak dapat di-parse, pesan error ditampilkan di tahap ini.
Tahap 2 — Pemetaan Kolom
Backend memanggil POST /api/contacts/import/preview dengan isi CSV mentah. Response berisi:
headers— nama kolom dari baris pertama CSVsample_rows— hingga 5 baris datatotal_rows— jumlah baris data keseluruhan
Frontend otomatis menebak pemetaan berdasarkan nama kolom:
| Nama kolom CSV (case-insensitive) | Field tujuan |
|---|---|
mengandung name | name |
mengandung phone atau mobile | phone_number |
mengandung email atau mail | email |
mengandung channel | channel |
mengandung tag | tags |
| lainnya | — skip — (diabaikan) |
Anda dapat mengubah pemetaan secara manual via dropdown sebelum melanjutkan. Kolom yang dipetakan ke — skip — tidak akan diimpor.
Tahap 3 — Preview
Menampilkan tabel sampel data beserta label field tujuan di bawah setiap header. Klik Import N Contacts untuk mengeksekusi.
Frontend mengirim POST /api/contacts/import/execute dengan body:
Code
Backend menggunakan ON CONFLICT (phone_number) DO UPDATE — kontak yang sudah ada berdasarkan phone_number akan diperbarui (nama dan email diisi jika kosong), bukan digandakan. Baris tanpa phone_number dan email dilewati (skipped).
channel_source untuk kontak yang diimpor via wizard di-set ke 'import' secara otomatis. Jika kolom channel dipetakan, nilainya digunakan untuk impor via endpoint multipart (POST /api/contacts/import), bukan via wizard JSON.
Tahap 4 — Hasil
| Metrik | Keterangan |
|---|---|
| Imported | Baris yang berhasil dimasukkan atau diperbarui |
| Updated | Ditampilkan di UI (dari field updated response) |
| Errors | Jumlah baris yang gagal |
Setelah selesai, klik Import More untuk memulai ulang atau View Contacts untuk kembali ke direktori kontak.
Format CSV yang didukung
Code
Kolom name, phone_number, email, dan channel adalah yang paling berguna. Minimal harus ada salah satu dari phone_number atau email di setiap baris — baris yang tidak memiliki keduanya dilewati tanpa error.
Riwayat pekerjaan impor
Endpoint GET /api/import-jobs mengembalikan hingga 100 entri riwayat impor terbaru, diurutkan dari yang terbaru. Setiap entri mencakup:
| Field | Keterangan |
|---|---|
id | UUID pekerjaan |
agent_id | UUID agen yang menjalankan impor |
file_name | Nama file CSV |
total_rows | Total baris dalam file |
imported_rows | Baris yang berhasil diimpor |
failed_rows | Baris yang gagal |
status | Status pekerjaan |
error_details | Detail error (JSON, opsional) |
created_at | Waktu mulai |
completed_at | Waktu selesai (null jika masih berjalan) |
Deteksi Duplikat
Rute frontend
/contacts/duplicates
Halaman ini menampilkan grup kontak yang berbagi nomor telepon atau alamat email yang sama. Memerlukan izin contacts.view.
Cara kerja deteksi
Backend (GET /api/contacts/duplicates) menjalankan dua query terpisah:
- Duplikat telepon — kontak yang
phone_number-nya muncul lebih dari sekali (tidak null, tidak kosong). - Duplikat email — kontak yang
email-nya muncul lebih dari sekali, dikecualikan jika kontak tersebut sudah masuk ke grup duplikat telepon.
Hasilnya dikelompokkan menjadi objek DuplicateGroup:
Code
Menggabungkan semua kontak dalam satu grup
Klik tombol Merge All pada kartu grup. Frontend secara otomatis:
- Mengurutkan kontak dalam grup berdasarkan
created_atascending — kontak tertua menjadi primary. - Memanggil
POST /api/contacts/{primary_id}/merge/{secondary_id}untuk setiap kontak non-primary secara berurutan.
Proses merge tidak dapat dibatalkan. Kontak secondary akan dihapus permanen setelah semua percakapannya dipindahkan ke primary.
Saran Merge
Rute frontend
/contacts/merge-suggestions
Halaman ini menampilkan pasangan kontak yang diduga duplikat beserta skor kepercayaan (confidence). Memerlukan izin contacts.manage.
Cara kerja saran
Backend (GET /api/contacts/merge-suggestions) menjalankan query serupa dengan deteksi duplikat, lalu menghasilkan pasangan primary–secondary di mana primary adalah kontak yang lebih lama (created_at lebih awal). Skor kepercayaan dihitung sebagai:
| Kondisi | Confidence |
|---|---|
| Nomor telepon sama dan nama sama | 0.95 (95%) |
| Nomor telepon sama, nama berbeda | 0.80 (80%) |
| Email sama dan nama sama | 0.95 (95%) |
| Email sama, nama berbeda | 0.80 (80%) |
Confidence ditampilkan sebagai badge berwarna:
| Rentang | Warna |
|---|---|
| ≥ 90% | Hijau |
| 70–89% | Amber |
| < 70% | Merah |
Setiap kartu menampilkan kontak Primary (latar hijau) dan Secondary (latar abu-abu). Secondary akan digabungkan ke dalam primary.
Menggabungkan dari halaman saran
Klik tombol Merge pada kartu saran. Frontend memanggil:
Code
Setelah berhasil, kartu saran yang bersangkutan dihapus dari daftar tanpa reload penuh.
Proses Merge Kontak
Endpoint POST /api/contacts/{primary_id}/merge/{secondary_id} menjalankan operasi berikut dalam satu transaksi database:
- Pindahkan percakapan — semua percakapan milik secondary dipindahkan ke primary (
UPDATE conversations SET contact_id = primary_id). - Gabungkan tags — array tags dari kedua kontak digabung dan dideduplikasi.
- Isi field kosong — field
name,email, danphone_numberpada primary diisi dari secondary jika primary kosong untuk field tersebut. - Hapus secondary — kontak secondary dihapus dari database.
- Catat activity log — aksi
merge_contactsdicatat di tabelactivity_logsbeserta metadata (nama/telepon primary & secondary, jumlah percakapan yang dipindah).
Merge tidak dapat dilakukan pada kontak yang sama (primary_id == secondary_id) — backend mengembalikan HTTP 400.
Contoh response sukses
Code
Riwayat Merge
Per kontak
Code
Mengembalikan semua entri merge di mana kontak ini pernah menjadi primary atau secondary.
Semua merge (admin)
Code
Mengembalikan hingga 200 entri merge terbaru di seluruh workspace.
Struktur entri riwayat
| Field | Keterangan |
|---|---|
id | UUID entri |
primary_contact_id | UUID kontak yang menerima (bertahan) |
secondary_contact_id | UUID kontak yang dihapus |
merged_by | UUID agen yang melakukan merge |
merge_data | JSON metadata: secondary_name, secondary_phone, conversations_transferred, dll. |
created_at | Waktu merge dilakukan |
Ringkasan Endpoint
| Aksi | Endpoint | Izin |
|---|---|---|
| Preview CSV | POST /api/contacts/import/preview | contacts.manage |
| Eksekusi impor (wizard) | POST /api/contacts/import/execute | contacts.manage |
| Impor via multipart | POST /api/contacts/import | contacts.manage |
| Riwayat pekerjaan impor | GET /api/import-jobs | Login |
| Deteksi duplikat | GET /api/contacts/duplicates | contacts.view |
| Saran merge | GET /api/contacts/merge-suggestions | contacts.manage |
| Gabungkan kontak | POST /api/contacts/{primary_id}/merge/{secondary_id} | contacts.manage |
| Riwayat merge (per kontak) | GET /api/contacts/{id}/merge-history | Login |
| Riwayat merge (semua) | GET /api/contacts/merge-history | Login |
Skema request dan response lengkap tersedia di API Reference.
Lihat juga
- Manajemen Kontak — direktori kontak, pencarian, dan detail kontak
- Activity Logs — log aksi
import_contactsdanmerge_contacts